tx · CmfQraCzeWc3HB2eie3GmzJgPqFwP8D8RWwVxEyuUoFo

3N6VmiwyYvN3mje3HrLWZJwpGpXerqPwiY1:  -0.01400000 Waves

2020.11.26 06:57 [1281874] smart account 3N6VmiwyYvN3mje3HrLWZJwpGpXerqPwiY1 > SELF 0.00000000 Waves

{ "type": 13, "id": "CmfQraCzeWc3HB2eie3GmzJgPqFwP8D8RWwVxEyuUoFo", "fee": 1400000, "feeAssetId": null, "timestamp": 1606363050860, "version": 2, "chainId": 84, "sender": "3N6VmiwyYvN3mje3HrLWZJwpGpXerqPwiY1", "senderPublicKey": "6d67Hi89AYURSDxe1L8huJrSeU9FSdfUJMXWvwZb8goX", "proofs": [ "4WiCy3exByZhSqW7HxAit7sYmi4e6EAykLpHj93YHPFBD1EGDkhLSYyoyjiYg2X69ymNbZ6DQg2jkgXsK3NobavF" ], "script": "base64:AAIEAAAAAAAAAGEIAhIGCgQICAgIEgYKBAgICAgSBAoCCAgSDgoMCAgICAgIAQgICAgIEg0KCwgICAgIAQgICAgIEgUKAwgICBIECgIICBIGCgQIAQEIEgQKAggIEgMKAQgSAwoBCBIDCgEIAAAAPAAAAAAJb3JhY2xlRmVlCQEAAAAFdmFsdWUAAAABCQAEJgAAAAECAAAAIzNOMnM1UnRhSFBCZW5Dc3gyRUNjb0ZSYllIeDNub1poWFcxAAAAAAhzaWduRGFwcAkBAAAABXZhbHVlAAAAAQkABCYAAAABAgAAACMzTkMyOGhTaXZybXNUVVhhWUQxeDZMMzYySjRacFVub1RkQgAAAAALZmVlUmVjZWl2ZXICAAAAIzNOMUU2dFhkZFJvVmFSZlE5ZFEzdmc1TGFXMmZzZDhIS3ViAAAAAAtzaWduQXNzZXRJZAEAAAAg6KVqvMp3QvJwYTI1Sk9Fg7m5HuWZZxfDcerZC6EEresAAAAAC3VzZG5Bc3NldElkAQAAACAP8hwSrOTEPJrsRhqrJaiw7LoHK0bMbYhy8LXikkkBtAAAAAAMd2F2ZXNBc3NldElkAQAAAAAAAAAAB3NpZ25DdXQAAAAAAAAAAAgAAAAAB3VzZG5DdXQAAAAAAAAAAAoAAAAACHdhdmVzQ3V0AAAAAAAAAAAKAAAAAAVjaHJpcwIAAAAjM01zRzZqUE5DclZKVXRZQjdYSkJ4Uzd1dFdzWEFmNG45VnAAAAAABGpvZXACAAAAIzNNem00Vkx3c045dVp3YlRNelBqM1h1eFY2a0VmQVI4VUROAAAAAA9XSElURUxJU1RFRE9OTFkGAAAAAAtkYXBwUnVubmluZwYAAAAADm1haW50ZW5hbmNlTVNHAgAAAB1TSUdOIEFydCBpcyB1bmRlciBtYWludGVuYW5jZQAAAAALdXNlckFsbG93ZWQCAAAAB0FMTE9XRUQAAAAADnVzZXJSZWdpc3RlcmVkAgAAAApSRUdJU1RFUkVEAAAAAAx1c2VyVmVyaWZpZWQCAAAACFZFUklGSUVEAAAAAA11c2VyU3VzcGVuZGVkAgAAAAlTVVNQRU5ERUQAAAAAC3VzZXJSZW1vdmVkAgAAAAdSRU1PVkVEAAAAABJ1c2VyQ2hhbmdlUmVxdWlyZWQCAAAAD0NIQU5HRV9SRVFVSVJFRAAAAAAQdXNlclVucmVnaXN0ZXJlZAIAAAAMVU5SRUdJU1RFUkVEAAAAAAl1c2VyUmVzZXQCAAAABVJFU0VUAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEAAAADa2V5BAAAAAckbWF0Y2gwCQAEHQAAAAIFAAAABHRoaXMFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAGU3RyaW5nBAAAAAFhBQAAAAckbWF0Y2gwBQAAAAFhAgAAAAABAAAAGWdldEludGVnZXJCeUtleUZyb21PcmFjbGUAAAABAAAAA2tleQQAAAAHJG1hdGNoMAkABBoAAAACBQAAAAlvcmFjbGVGZWUFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAFhBQAAAAckbWF0Y2gwBQAAAAFhCQAAAgAAAAECAAAAH0ludGVnZXIgdW5kZWZpbmUgb3IgMCBpbiBvcmFjbGUBAAAAD2dldEludGVnZXJCeUtleQAAAAEAAAADa2V5BAAAAAckbWF0Y2gwCQAEGgAAAAIFAAAABHRoaXMFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAFpBQAAAAckbWF0Y2gwBQAAAAFpAAAAAAAAAAAAAQAAAA9nZXRCb29sZWFuQnlLZXkAAAABAAAAA2tleQQAAAAHJG1hdGNoMAkABBsAAAACBQAAAAR0aGlzBQAAAANrZXkDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAB0Jvb2xlYW4EAAAAAWkFAAAAByRtYXRjaDAFAAAAAWkHAQAAABRjaGVja1NpZ25DZXJ0aWZpY2F0ZQAAAAMAAAAGc2lnbklEAAAABU93bmVyAAAACnNoYTI1Nkhhc2gEAAAAByRtYXRjaDAJAAQdAAAAAgUAAAAIc2lnbkRhcHAJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGRhdGFfZmNfBQAAAAZzaWduSUQCAAAAAV8FAAAABU93bmVyAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAWEFAAAAByRtYXRjaDADCQEAAAAIY29udGFpbnMAAAACBQAAAAFhBQAAAApzaGEyNTZIYXNoBgcHAQAAAAt2YWxpZGF0ZUNJRAAAAAEAAAADY2lkAwMJAABmAAAAAgAAAAAAAAAASwkAATEAAAABBQAAAANjaWQJAABmAAAAAgAAAAAAAAAAPAkAATEAAAABCQABkQAAAAIJAAS1AAAAAgUAAAADY2lkAgAAAAEvAAAAAAAAAAAABwkAAGYAAAACAAAAAAAAAAAQCQABMQAAAAEJAAGRAAAAAgkABLUAAAACBQAAAANjaWQCAAAAAS8AAAAAAAAAAAEHAQAAAAx2YWxpZGF0ZUhhc2gAAAABAAAABGhhc2gJAABmAAAAAgAAAAAAAAAAQQkAATEAAAABBQAAAARoYXNoAQAAAAtrZXlVc2VyQWRkcgAAAAEAAAAGY2FsbGVyCQABLAAAAAICAAAABXVzZXJfBQAAAAZjYWxsZXIBAAAAC2tleVVzZXJOYW1lAAAAAQAAAAZjYWxsZXIJAAEsAAAAAgIAAAAKdXNlcl9uYW1lXwUAAAAGY2FsbGVyAQAAAAtrZXlVc2VyRGVzYwAAAAEAAAAGY2FsbGVyCQABLAAAAAICAAAACnVzZXJfZGVzY18FAAAABmNhbGxlcgEAAAANa2V5VXNlclNvY2lhbAAAAAEAAAAGY2FsbGVyCQABLAAAAAICAAAADHVzZXJfc29jaWFsXwUAAAAGY2FsbGVyAQAAAAxrZXlVc2VyVGh1bWIAAAABAAAABmNhbGxlcgkAASwAAAACAgAAAAt1c2VyX3RodW1iXwUAAAAGY2FsbGVyAQAAAA1rZXlVc2VyU3RhdHVzAAAAAQAAAAZjYWxsZXIJAAEsAAAAAgIAAAAMdXNlcl9zdGF0dXNfBQAAAAZjYWxsZXIBAAAAC2tleVVzZXJEYXRlAAAAAQAAAAZjYWxsZXIJAAEsAAAAAgIAAAAKdXNlcl9kYXRlXwUAAAAGY2FsbGVyAQAAAAprZXlBcnREYXRlAAAAAgAAAAZjYWxsZXIAAAAFYXJ0SWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACWFydF9kYXRlXwUAAAAFYXJ0SWQCAAAAAV8FAAAABmNhbGxlcgEAAAAKa2V5QXJ0TmFtZQAAAAIAAAAGY2FsbGVyAAAABWFydElkCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAlhcnRfbmFtZV8FAAAABWFydElkAgAAAAFfBQAAAAZjYWxsZXIBAAAACmtleUFydERlc2MAAAACAAAABmNhbGxlcgAAAAVhcnRJZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAJYXJ0X2Rlc2NfBQAAAAVhcnRJZAIAAAABXwUAAAAGY2FsbGVyAQAAABBrZXlBcnREaXNwbGF5Q2lkAAAAAgAAAAZjYWxsZXIAAAAFYXJ0SWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAEGFydF9kaXNwbGF5X2NpZF8FAAAABWFydElkAgAAAAFfBQAAAAZjYWxsZXIBAAAAEGtleUFydEV4cG9ydEhhc2gAAAACAAAABmNhbGxlcgAAAAVhcnRJZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAQYXJ0X2V4cG9ydF9oYXNoXwUAAAAFYXJ0SWQCAAAAAV8FAAAABmNhbGxlcgEAAAAPa2V5QXJ0RXhwb3J0Q2lkAAAAAgAAAAZjYWxsZXIAAAAFYXJ0SWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAD2FydF9leHBvcnRfY2lkXwUAAAAFYXJ0SWQCAAAAAV8FAAAABmNhbGxlcgEAAAANa2V5QXJ0TWF4TWludAAAAAIAAAAGY2FsbGVyAAAABWFydElkCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAxhcnRfbWF4bWludF8FAAAABWFydElkAgAAAAFfBQAAAAZjYWxsZXIBAAAADGtleUFydFNpZ25JRAAAAAIAAAAGY2FsbGVyAAAABWFydElkCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAthcnRfc2lnbmlkXwUAAAAFYXJ0SWQCAAAAAV8FAAAABmNhbGxlcgEAAAAMa2V5QXJ0SXNzdWVkAAAAAgAAAAZjYWxsZXIAAAAFYXJ0SWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAC2FydF9pc3N1ZWRfBQAAAAVhcnRJZAIAAAABXwUAAAAGY2FsbGVyAQAAAAxrZXlBcnRPblNhbGUAAAACAAAABmNhbGxlcgAAAAVhcnRJZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAALYXJ0X29uc2FsZV8FAAAABWFydElkAgAAAAFfBQAAAAZjYWxsZXIBAAAAEWtleUFydExpY2VuY2VIYXNoAAAAAgAAAAZjYWxsZXIAAAAFYXJ0SWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAEWFydF9saWNlbmNlX2hhc2hfBQAAAAVhcnRJZAIAAAABXwUAAAAGY2FsbGVyAQAAABBrZXlBcnRMaWNlbmNlQ2lkAAAAAgAAAAZjYWxsZXIAAAAFYXJ0SWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAEGFydF9saWNlbmNlX2NpZF8FAAAABWFydElkAgAAAAFfBQAAAAZjYWxsZXIBAAAACmtleUFydFRhZ3MAAAACAAAABmNhbGxlcgAAAAVhcnRJZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAJYXJ0X3RhZ3NfBQAAAAVhcnRJZAIAAAABXwUAAAAGY2FsbGVyAQAAAAprZXlBcnRUeXBlAAAAAgAAAAZjYWxsZXIAAAAFYXJ0SWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACWFydF90eXBlXwUAAAAFYXJ0SWQCAAAAAV8FAAAABmNhbGxlcgEAAAALa2V5QXJ0UHJpY2UAAAACAAAABmNhbGxlcgAAAAVhcnRJZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAKYXJ0X3ByaWNlXwUAAAAFYXJ0SWQCAAAAAV8FAAAABmNhbGxlcgEAAAAVa2V5QXJ0QXNzZXRJZEFjY2VwdGVkAAAAAgAAAAZjYWxsZXIAAAAFYXJ0SWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAEmFydF9hc3NldEFjY2VwdGVkXwUAAAAFYXJ0SWQCAAAAAV8FAAAABmNhbGxlcgEAAAAKa2V5QXJ0RmxhZwAAAAIAAAAGY2FsbGVyAAAABWFydElkCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAlhcnRfZmxhZ18FAAAABWFydElkAgAAAAFfBQAAAAZjYWxsZXIBAAAAFGtleUFydEhhc2hCeVR4aWRBZGRyAAAAAgAAAAZjYWxsZXIAAAAEdHhpZAkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAATZ2V0X2hhc2hieXR4aWRhZGRyXwUAAAAEdHhpZAIAAAABXwUAAAAGY2FsbGVyAQAAABFrZXlBcnRPd25lckJ5SGFzaAAAAAEAAAAKc2hhMjU2SGFzaAkAASwAAAACAgAAABJnZXRfb3duZXJfYnlfaGFzaF8FAAAACnNoYTI1Nkhhc2gBAAAAE2tleUFydEFydGlkQnlTaWduaWQAAAACAAAABmNhbGxlcgAAAAZzaWduSWQJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAEmdldF9hcnRpZGJ5c2lnbmlkXwUAAAAGc2lnbklkAgAAAAFfBQAAAAZjYWxsZXIBAAAAFWtleUFydFR4aWRCeUhhc2hPd25lcgAAAAIAAAAKc2hhMjU2SGFzaAAAAAZjYWxsZXIJAAEsAAAAAgIAAAAXZ2V0X3R4aWRfYnlfaGFzaF9vd25lcl8JAAJYAAAAAQkAC1QAAAABCQABmwAAAAEJAAEsAAAAAgUAAAAKc2hhMjU2SGFzaAUAAAAGY2FsbGVyAQAAAA52YWxpZGF0ZUFsbENJRAAAAAMAAAAKY2lkRGlzcGxheQAAAAljaWRFeHBvcnQAAAAKY2lkTGljZW5jZQMDCQEAAAACIT0AAAACBQAAAApjaWREaXNwbGF5AgAAAAAJAQAAAAEhAAAAAQkBAAAAC3ZhbGlkYXRlQ0lEAAAAAQUAAAAKY2lkRGlzcGxheQcJAAACAAAAAQIAAAARV3JvbmcgRGlzcGxheSBDSUQDAwkBAAAAAiE9AAAAAgUAAAAJY2lkRXhwb3J0AgAAAAAJAQAAAAEhAAAAAQkBAAAAC3ZhbGlkYXRlQ0lEAAAAAQUAAAAJY2lkRXhwb3J0BwkAAAIAAAABAgAAABBXcm9uZyBFeHBvcnQgQ0lEAwMJAQAAAAIhPQAAAAIFAAAACmNpZExpY2VuY2UCAAAAAAkBAAAAASEAAAABCQEAAAALdmFsaWRhdGVDSUQAAAABBQAAAApjaWRMaWNlbmNlBwkAAAIAAAABAgAAABFXcm9uZyBMaWNlbmNlIENJRAYBAAAAD3ZhbGlkYXRlQWxsSGFzaAAAAAIAAAAMc2hhMjU2RXhwb3J0AAAADXNoYTI1NkxpY2VuY2UDAwkBAAAAAiE9AAAAAgUAAAAMc2hhMjU2RXhwb3J0AgAAAAAJAQAAAAEhAAAAAQkBAAAADHZhbGlkYXRlSGFzaAAAAAEFAAAADHNoYTI1NkV4cG9ydAcJAAACAAAAAQIAAAAYRXhwb3J0IEhhc2ggNjQgY2hhci4gbWF4AwMJAQAAAAIhPQAAAAIFAAAADXNoYTI1NkxpY2VuY2UCAAAAAAkBAAAAASEAAAABCQEAAAAMdmFsaWRhdGVIYXNoAAAAAQUAAAANc2hhMjU2TGljZW5jZQcJAAACAAAAAQIAAAAZTGljZW5jZSBIYXNoIDY0IGNoYXIuIG1heAYBAAAADnZhbGlkYXRlU3RyaW5nAAAAAgAAAANzdHIAAAADbWF4AwkAAAAAAAACCQABMQAAAAEFAAAAA3N0cgAAAAAAAAAAAAkAAAIAAAABAgAAABhGaWVsZCBjYW5ub3QgYmUgaXMgZW1wdHkDCQAAZgAAAAIJAAExAAAAAQUAAAADc3RyBQAAAANtYXgJAAACAAAAAQkAASwAAAACBQAAAANzdHICAAAADCBpcyB0b28gbG9uZwYAAAAMAAAAAWkBAAAADHJlZ2lzdGVyVXNlcgAAAAQAAAAEbmFtZQAAAAtkZXNjcmlwdGlvbgAAAAV0aHVtYgAAAAZzb2NpYWwDCQEAAAABIQAAAAEFAAAAC2RhcHBSdW5uaW5nCQAAAgAAAAEFAAAADm1haW50ZW5hbmNlTVNHBAAAAAZjYWxsZXIJAAQlAAAAAQkBAAAAFGFkZHJlc3NGcm9tUHVibGljS2V5AAAAAQgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5BAAAAAtjYW5SZWdpc3RlcgkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQkBAAAADWtleVVzZXJTdGF0dXMAAAABBQAAAAZjYWxsZXIEAAAAAmlkCQACWAAAAAEIBQAAAAFpAAAADXRyYW5zYWN0aW9uSWQEAAAACXRpbWVzdGFtcAgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXADAwkAAAAAAAACBQAAAAtjYW5SZWdpc3RlcgUAAAANdXNlclN1c3BlbmRlZAYJAAAAAAAAAgUAAAALY2FuUmVnaXN0ZXIFAAAAC3VzZXJSZW1vdmVkCQAAAgAAAAECAAAAG0FjY291bnQgc3VzcGVuZGVkLyByZW1vdmVkLgMJAAAAAAAAAgUAAAALY2FuUmVnaXN0ZXIFAAAADnVzZXJSZWdpc3RlcmVkCQAAAgAAAAECAAAAEkFscmVhZHkgcmVnaXN0ZXJlZAMDCQAAAAAAAAIFAAAAC2NhblJlZ2lzdGVyAgAAAAAFAAAAD1dISVRFTElTVEVET05MWQcJAAACAAAAAQIAAAAjQ2FuJ3QgcmVnaXN0ZXIsIGdldCBhcHByb3ZlZCBmaXJzdC4DAwkAAAAAAAACBQAAAARuYW1lAgAAAAAGCQAAAAAAAAIFAAAAC2Rlc2NyaXB0aW9uAgAAAAAJAAACAAAAAQIAAAAkTmFtZSBhbmQgZGVzY3JpcHRpb24gY2Fubm90IGJlIGVtcHR5AwkAAGYAAAACCQABMQAAAAEFAAAAC2Rlc2NyaXB0aW9uAAAAAAAAAAJYCQAAAgAAAAECAAAAGTYwMCBDaGFyLiBtYXggZGVzY3JpcHRpb24DCQAAZgAAAAIJAAExAAAAAQUAAAAEbmFtZQAAAAAAAAAALQkAAAIAAAABAgAAABE0NSBDaGFyLiBtYXggbmFtZQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAC2tleVVzZXJEYXRlAAAAAQUAAAAGY2FsbGVyBQAAAAl0aW1lc3RhbXAJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAC2tleVVzZXJBZGRyAAAAAQUAAAAGY2FsbGVyCQABLAAAAAIJAAEsAAAAAgUAAAACaWQCAAAAAV8JAAGkAAAAAQUAAAAJdGltZXN0YW1wCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAAtrZXlVc2VyTmFtZQAAAAEFAAAABmNhbGxlcgUAAAAEbmFtZQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAALa2V5VXNlckRlc2MAAAABBQAAAAZjYWxsZXIFAAAAC2Rlc2NyaXB0aW9uCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAA1rZXlVc2VyU29jaWFsAAAAAQUAAAAGY2FsbGVyBQAAAAZzb2NpYWwJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAADGtleVVzZXJUaHVtYgAAAAEFAAAABmNhbGxlcgUAAAAFdGh1bWIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAADWtleVVzZXJTdGF0dXMAAAABBQAAAAZjYWxsZXIFAAAADnVzZXJSZWdpc3RlcmVkCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAICAAAADmxhc3RfaW52b2tlX2lkBQAAAAJpZAUAAAADbmlsAAAAAWkBAAAACnVwZGF0ZVVzZXIAAAAEAAAABG5hbWUAAAALZGVzY3JpcHRpb24AAAAFdGh1bWIAAAAGc29jaWFsAwkBAAAAASEAAAABBQAAAAtkYXBwUnVubmluZwkAAAIAAAABBQAAAA5tYWludGVuYW5jZU1TRwQAAAAGY2FsbGVyCQAEJQAAAAEJAQAAABRhZGRyZXNzRnJvbVB1YmxpY0tleQAAAAEIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQQAAAACaWQJAAJYAAAAAQgFAAAAAWkAAAANdHJhbnNhY3Rpb25JZAQAAAAJY2FuVXBkYXRlCQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABCQEAAAANa2V5VXNlclN0YXR1cwAAAAEFAAAABmNhbGxlcgMDCQAAAAAAAAIFAAAACWNhblVwZGF0ZQUAAAANdXNlclN1c3BlbmRlZAYJAAAAAAAAAgUAAAAJY2FuVXBkYXRlBQAAAAt1c2VyUmVtb3ZlZAkAAAIAAAABAgAAABtBY2NvdW50IHN1c3BlbmRlZC8gcmVtb3ZlZC4DAwkAAAAAAAACBQAAAAljYW5VcGRhdGUCAAAAAAYJAAAAAAAAAgUAAAAJY2FuVXBkYXRlBQAAAAt1c2VyQWxsb3dlZAkAAAIAAAABAgAAAA5SZWdpc3RlciBmaXJzdAMDCQAAAAAAAAIFAAAABG5hbWUCAAAAAAYJAAAAAAAAAgUAAAALZGVzY3JpcHRpb24CAAAAAAkAAAIAAAABAgAAACJOYW1lICYgZGVzY3JpcHRpb24gY2Fubm90IGJlIGVtcHR5AwkAAGYAAAACCQABMQAAAAEFAAAAC2Rlc2NyaXB0aW9uAAAAAAAAAAJYCQAAAgAAAAECAAAAHTYwMCBDaGFyLiBtYXggZm9yIGRlc2NyaXB0aW9uAwkAAGYAAAACCQABMQAAAAEFAAAABG5hbWUAAAAAAAAAAC0JAAACAAAAAQIAAAARNDUgQ2hhci4gbWF4IG5hbWUJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAC2tleVVzZXJOYW1lAAAAAQUAAAAGY2FsbGVyBQAAAARuYW1lCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAAtrZXlVc2VyRGVzYwAAAAEFAAAABmNhbGxlcgUAAAALZGVzY3JpcHRpb24JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAADWtleVVzZXJTb2NpYWwAAAABBQAAAAZjYWxsZXIFAAAABnNvY2lhbAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAMa2V5VXNlclRodW1iAAAAAQUAAAAGY2FsbGVyBQAAAAV0aHVtYgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAAA5sYXN0X2ludm9rZV9pZAUAAAACaWQFAAAAA25pbAAAAAFpAQAAABBjaGFuZ2VVc2VyU3RhdHVzAAAAAgAAAAdhZGRyZXNzAAAABnN0YXR1cwMJAQAAAAEhAAAAAQUAAAALZGFwcFJ1bm5pbmcJAAACAAAAAQUAAAAObWFpbnRlbmFuY2VNU0cEAAAABmNhbGxlcgkABCUAAAABCQEAAAAUYWRkcmVzc0Zyb21QdWJsaWNLZXkAAAABCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkEAAAAAmlkCQACWAAAAAEIBQAAAAFpAAAADXRyYW5zYWN0aW9uSWQEAAAADWN1cnJlbnRTdGF0dXMJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAAA1rZXlVc2VyU3RhdHVzAAAAAQUAAAAHYWRkcmVzcwQAAAALc3RhdHVzVG9TZXQDCQAAAAAAAAIFAAAABnN0YXR1cwUAAAAMdXNlclZlcmlmaWVkBQAAAAx1c2VyVmVyaWZpZWQDCQAAAAAAAAIFAAAABnN0YXR1cwUAAAAOdXNlclJlZ2lzdGVyZWQFAAAADnVzZXJSZWdpc3RlcmVkAwkAAAAAAAACBQAAAAZzdGF0dXMFAAAADXVzZXJTdXNwZW5kZWQFAAAADXVzZXJTdXNwZW5kZWQDCQAAAAAAAAIFAAAABnN0YXR1cwUAAAALdXNlclJlbW92ZWQFAAAAC3VzZXJSZW1vdmVkAwkAAAAAAAACBQAAAAZzdGF0dXMFAAAAC3VzZXJBbGxvd2VkBQAAAAt1c2VyQWxsb3dlZAMJAAAAAAAAAgUAAAAGc3RhdHVzBQAAABJ1c2VyQ2hhbmdlUmVxdWlyZWQFAAAA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ACZPbmx5IFNJR04gdG9rZW4gYWNjZXB0ZWQgYXQgdGhlIG1vbWVudAQAAAAZY3VycmVudENlcnRpZmljYXRpb25QcmljZQkBAAAAGWdldEludGVnZXJCeUtleUZyb21PcmFjbGUAAAABCQABLAAAAAICAAAAEmNlcnRpZmljYXRpb25fZmVlXwkAAlgAAAABBQAAAAtzaWduQXNzZXRJZAMJAQAAAAIhPQAAAAIFAAAABmFtb3VudAUAAAAZY3VycmVudENlcnRpZmljYXRpb25QcmljZQkAAAIAAAABCQABLAAAAAICAAAAGVBheW1lbnQgYW1vdW50IHNob3VsZCBiZSAJAAGkAAAAAQUAAAAZY3VycmVudENlcnRpZmljYXRpb25QcmljZQQAAAAKZW50cnlFeGlzdAkBAAAADmdldFN0cmluZ0J5S2V5AAAAAQkBAAAAFWtleUFydFR4aWRCeUhhc2hPd25lcgAAAAIFAAAACnNoYTI1Nkhhc2gFAAAABmNhbGxlcgMJAQAAAAIhPQAAAAIFAAAACmVudHJ5RXhpc3QCAAAAAAkAAAIAAAABAgAAABRZb3UgYWxyZWFkeSBhZGRlZCBpdAQAAAAJaGFzaEV4aXN0CQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABCQEAAAARa2V5QXJ0T3duZXJCeUhhc2gAAAABBQAAAApzaGEyNTZIYXNoAwkBAAAAAiE9AAAAAgUAAAAJaGFzaEV4aXN0AgAAAAAJAAACAAAAAQIAAAAXSGFzaCBhbHJlYWR5IHJlZ2lzdGVyZWQEAAAAD2lzU2lnbkNlcnRpZmllZAkBAAAAFGNoZWNrU2lnbkNlcnRpZmljYXRlAAAAAwUAAAAGc2lnbklEBQAAAAZjYWxsZXIFAAAACnNoYTI1Nkhhc2gDCQEAAAABIQAAAAEFAAAAD2lzU2lnbkNlcnRpZmllZAkAAAIAAAABAgAAACxTaWduIENlcnRpZmljYXRlIG5vdCBmb3VuZCBmb3IgdGhpcyBhZGRyZXNzLgMJAAAAAAAAAgkAATEAAAABBQAAAApjaWREaXNwbGF5AAAAAAAAAAAACQAAAgAAAAECAAAAG0Rpc3BsYXkgQ0lEIGNhbm5vdCBiZSBlbXB0eQMJAQAAAAEhAAAAAQkBAAAADnZhbGlkYXRlU3RyaW5nAAAAAgUAAAAEbmFtZQAAAAAAAAAAZAkAAAIAAAABAgAAABIxMDAgQ2hhci4gbWF4IG5hbWUDCQEAAAABIQAAAAEJAQAAAA52YWxpZGF0ZVN0cmluZwAAAAIFAAAAC2Rlc2NyaXB0aW9uAAAAAAAAAAPoCQAAAgAAAAECAAAAGjEwMDAgQ2hhci4gbWF4IGRlc2NyaXB0aW9uAwkAAGYAAAACCQABkAAAAAEJAAS1AAAAAgUAAAAEdGFncwIAAAABLAAAAAAAAAAABQkAAAIAAAABAgAAAAs1IHRhZ3MgbWF4LgQAAAAQdXNlcklzUmVnaXN0ZXJlZAQAAAAHJG1hdGNoMAkABB0AAAACBQAAAAR0aGlzCQABLAAAAAICAAAADHVzZXJfc3RhdHVzXwUAAAAGY2FsbGVyAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAXMFAAAAByRtYXRjaDAFAAAAAXMFAAAAEHVzZXJVbnJlZ2lzdGVyZWQEAAAACXRpbWVzdGFtcAgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXADAwkBAAAACWlzRGVmaW5lZAAAAAEFAAAAEHVzZXJJc1JlZ2lzdGVyZWQJAAAAAAAAAgUAAAAQdXNlcklzUmVnaXN0ZXJlZAUAAAAQdXNlclVucmVnaXN0ZXJlZAcJAAACAAAAAQIAAAAxUmVnaXN0ZXIgdGhpcyBhY2NvdW50IGZpcnN0IHdpdGggIlVzZXIgaW5mb3MiIHRhYgMJAAAAAAAAAgUAAAAQdXNlcklzUmVnaXN0ZXJlZAUAAAANdXNlclN1c3BlbmRlZAkAAAIAAAABAgAAABFBY2NvdW50IHN1c3BlbmRlZAMJAAAAAAAAAgUAAAAQdXNlcklzUmVnaXN0ZXJlZAUAAAALdXNlclJlbW92ZWQJAAACAAAAAQIAAAAPQWNjb3VudCByZW1vdmVkAwkAAGYAAAACBQAAAAdtYXhtaW50AAAAAAAAAAAKCQAAAgAAAAECAAAADzEwIGVkaXRpb25zIG1heAMJAQAAAAIhPQAAAAIJAAExAAAAAQUAAAAKc2hhMjU2SGFzaAAAAAAAAAAAQAkAAAIAAAABAgAAABFIYXNoIDY0IGNoYXIuIG1heAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAARa2V5QXJ0T3duZXJCeUhhc2gAAAABBQAAAApzaGEyNTZIYXNoBQAAAAZjYWxsZXIJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAFWtleUFydFR4aWRCeUhhc2hPd25lcgAAAAIFAAAACnNoYTI1Nkhhc2gFAAAABmNhbGxlcgUAAAAFYXJ0SWQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAAAprZXlBcnREYXRlAAAAAgUAAAAGY2FsbGVyBQAAAAVhcnRJZAUAAAAJdGltZXN0YW1wCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAAprZXlBcnROYW1lAAAAAgUAAAAGY2FsbGVyBQAAAAVhcnRJZAUAAAAEbmFtZQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAKa2V5QXJ0RGVzYwAAAAIFAAAABmNhbGxlcgUAAAAFYXJ0SWQFAAAAC2Rlc2NyaXB0aW9uCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABBrZXlBcnREaXNwbGF5Q2lkAAAAAgUAAAAGY2FsbGVyBQAAAAVhcnRJZAUAAAAKY2lkRGlzcGxheQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAPa2V5QXJ0RXhwb3J0Q2lkAAAAAgUAAAAGY2FsbGVyBQAAAAVhcnRJZAUAAAAJY2lkRXhwb3J0CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABBrZXlBcnRFeHBvcnRIYXNoAAAAAgUAAAAGY2FsbGVyBQAAAAVhcnRJZAUAAAAMc2hhMjU2RXhwb3J0CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABFrZXlBcnRMaWNlbmNlSGFzaAAAAAIFAAAABmNhbGxlcgUAAAAFYXJ0SWQFAAAADXNoYTI1NkxpY2VuY2UJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEGtleUFydExpY2VuY2VDaWQAAAACBQAAAAZjYWxsZXIFAAAABWFydElkBQAAAApjaWRMaWNlbmNlCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAAprZXlBcnRUeXBl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dHhpZAUAAAALZGVzY3JpcHRpb24JAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEGtleUFydERpc3BsYXlDaWQAAAACBQAAAAZjYWxsZXIFAAAABHR4aWQFAAAACmNpZERpc3BsYXkJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAD2tleUFydEV4cG9ydENpZAAAAAIFAAAABmNhbGxlcgUAAAAEdHhpZAUAAAAJY2lkRXhwb3J0CQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABBrZXlBcnRFeHBvcnRIYXNoAAAAAgUAAAAGY2FsbGVyBQAAAAR0eGlkBQAAAAxzaGEyNTZFeHBvcnQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEGtleUFydExpY2VuY2VDaWQAAAACBQAAAAZjYWxsZXIFAAAABHR4aWQFAAAACmNpZExpY2VuY2UJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEWtleUFydExpY2VuY2VIYXNoAAAAAgUAAAAGY2FsbGVyBQAAAAR0eGlkBQAAAA1zaGEyNTZMaWNlbmNlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAANa2V5QXJ0TWF4TWludAAAAAIFAAAABmNhbGxlcgUAAAAEdHhpZAUAAAAHbWF4bWludAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAKa2V5QXJ0VGFncwAAAAIFAAAABmNhbGxlcgUAAAAEdHhpZAUAAAAEdGFncwkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAKa2V5QXJ0VHlwZQAAAAIFAAAABmNhbGxlcgUAAAAEdHhpZAUAAAAEdHlwZQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAAA5sYXN0X2ludm9rZV9pZAUAAAAIdXBkYXRlSWQFAAAAA25pbAkAAAIAAAABAgAAAA5BbHJlYWR5IG1pbnRlZAAAAAFpAQAAAAtmbGFnQXJ0d29yawAAAAMAAAAFYXJ0SWQAAAAEYWRkcgAAAARmbGFnBAAAAAZjYWxsZXIJAAQlAAAAAQkBAAAAFGFkZHJlc3NGcm9tUHVibGljS2V5AAAAAQgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5BAAAAAJpZAkAAlgAAAABCAUAAAABaQAAAA10cmFuc2FjdGlvbklkAwkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIJAARMAAAAAgUAAAAFY2hyaXMJAARMAAAAAgUAAAAEam9lcAUAAAADbmlsBQAAAAZjYWxsZXIDCQAAAAAAAAIFAAAABGZsYWcCAAAAB0NPTlNFTlQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAACmtleUFydEZsYWcAAAACBQAAAARhZGRyBQAAAAVhcnRJZAUAAAAEZmxhZwkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAAA5sYXN0X2ludm9rZV9pZAUAAAACaWQFAAAAA25pbAMJAAAAAAAAAgUAAAAEZmxhZwIAAAAACQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAAAprZXlBcnRGbGFnAAAAAgUAAAAEYWRkcgUAAAAFYXJ0SWQFAAAABGZsYWcJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAAObGFzdF9pbnZva2VfaWQFAAAAAmlkBQAAAANuaWwDCQAAAAAAAAIFAAAABGZsYWcCAAAAB0lMTEVHQUwJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAACmtleUFydEZsYWcAAAACBQAAAARhZGRyBQAAAAVhcnRJZAUAAAAEZmxhZwkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAKa2V5QXJ0TmFtZQAAAAIFAAAABGFkZHIFAAAABWFydElkAgAAAA9JTExFR0FMIENPTlRFTlQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAACmtleUFydERlc2MAAAACBQAAAARhZGRyBQAAAAVhcnRJZAIAAAAPSUxMRUdBTCBDT05URU5UCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAQAAABBrZXlBcnREaXNwbGF5Q2lkAAAAAgUAAAAEYWRkcgUAAAAFYXJ0SWQCAAAAAAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAPa2V5QXJ0RXhwb3J0Q2lkAAAAAgUAAAAEYWRkcgUAAAAFYXJ0SWQCAAAAAAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAQa2V5QXJ0TGljZW5jZUNpZAAAAAIFAAAABGFkZHIFAAAABWFydElkAgAAAAAJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAAObGFzdF9pbnZva2VfaWQFAAAAAmlkBQAAAANuaWwJAAACAAAAAQkAASwAAAACAgAAAA1Vbmtub3cgc3RhdHVzBQAAAARmbGFnCQAAAgAAAAECAAAAAm5vAAAAAWkBAAAADWRlbGV0ZUFydHdvcmsAAAACAAAABWFydElkAAAABGFkZHIEAAAABmNhbGxlcgkABCUAAAABCQEAAAAUYWRkcmVzc0Zyb21QdWJsaWNLZXkAAAABCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkEAAAAAmlkCQACWAAAAAEIBQAAAAFpAAAADXRyYW5zYWN0aW9uSWQEAAAADGFkZHJlc3NUb1VzZQMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACCQAETAAAAAIFAAAABWNocmlzCQAETAAAAAIFAAAABGpvZXAFAAAAA25pbAUAAAAGY2FsbGVyBQAAAARhZGRyBQAAAAZjYWxsZXIEAAAACmVudHJ5RXhpc3QEAAAAByRtYXRjaDAJAAQdAAAAAgUAAAAEdGhpcwkBAAAACmtleUFydE5hbWUAAAACBQAAAAxhZGRyZXNzVG9Vc2UFAAAABWFydElkAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAXMFAAAAByRtYXRjaDAFAAAAAXMJAAACAAAAAQIAAAAPTm8gYXJ0IG1hdGNoaW5nBAAAAA1hcnR3b3JrTWludGVkBAAAAAckbWF0Y2gwCQAEGgAAAAIFAAAABHRoaXMJAQAAAAxrZXlBcnRJc3N1ZWQAAAACBQAAAAxhZGRyZXNzVG9Vc2UFAAAABWFydElkAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAAWIFAAAAByRtYXRjaDADCQEAAAACIT0AAAACBQAAAAFiAAAAAAAAAAAABgcHBAAAAAdtYXhNaW50CQEAAAAPZ2V0SW50ZWdlckJ5S2V5AAAAAQkBAAAADWtleUFydE1heE1pbnQAAAACBQAAAAxhZGRyZXNzVG9Vc2UFAAAABWFydElkBAAAAApzaGEyNTZIYXNoBAAAAAckbWF0Y2gwCQAEHQAAAAIFAAAABHRoaXMJAQAAABRrZXlBcnRIYXNoQnlUeGlkQWRkcgAAAAIFAAAADGFkZHJlc3NUb1VzZQUAAAAFYXJ0SWQDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABlN0cmluZwQAAAABcwUAAAAHJG1hdGNoMAUAAAABcwkAAAIAAAABAgAAABRObyBhcnQgaGFzaCBtYXRjaGluZwQAAAAGc2lnbklEBAAAAAckbWF0Y2gwCQAEHQAAAAIFAAAABHRoaXMJAQAAAAxrZXlBcnRTaWduSUQAAAACBQAAAAxhZGRyZXNzVG9Vc2UFAAAABWFydElkAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAAZTdHJpbmcEAAAAAXMFAAAAByRtYXRjaDAFAAAAAXMJAAACAAAAAQIAAAATTm8gU0lHTiBJRCBtYXRjaGluZwQAAAAMZGF0YVRvRGVsZXRlCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEJAQAAAAprZXlBcnREYXRlAAAAAgUAAAAMYWRkcmVzc1RvVXNlBQAAAAVhcnRJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAKa2V5QXJ0TmFtZQAAAAIFAAAADGFkZHJlc3NUb1VzZQUAAAAFYXJ0SWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAACmtleUFydERlc2MAAAACBQAAAAxhZGRyZXNzVG9Vc2UFAAAABWFydElkCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEJAQAAABBrZXlBcnREaXNwbGF5Q2lkAAAAAgUAAAAMYWRkcmVzc1RvVXNlBQAAAAVhcnRJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAPa2V5QXJ0RXhwb3J0Q2lkAAAAAgUAAAAMYWRkcmVzc1RvVXNlBQAAAAVhcnRJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAQa2V5QXJ0RXhwb3J0SGFzaAAAAAIFAAAADGFkZHJlc3NUb1VzZQUAAAAFYXJ0SWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAAEWtleUFydExpY2VuY2VIYXNoAAAAAgUAAAAMYWRkcmVzc1RvVXNlBQAAAAVhcnRJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAAQa2V5QXJ0TGljZW5jZUNpZAAAAAIFAAAADGFkZHJlc3NUb1VzZQUAAAAFYXJ0SWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAACmtleUFydFR5cGUAAAACBQAAAAxhZGRyZXNzVG9Vc2UFAAAABWFydElkCQAETAAAAAIJAQAAAAtEZWxldGVFbnRyeQAAAAEJAQAAAAprZXlBcnRUYWdzAAAAAgUAAAAMYWRkcmVzc1RvVXNlBQAAAAVhcnRJZAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAANa2V5QXJ0TWF4TWludAAAAAIFAAAADGFkZHJlc3NUb1VzZQUAAAAFYXJ0SWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAADGtleUFydFNpZ25JRAAAAAIFAAAADGFkZHJlc3NUb1VzZQUAAAAFYXJ0SWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAADGtleUFydElzc3VlZAAAAAIFAAAADGFkZHJlc3NUb1VzZQUAAAAFYXJ0SWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAADGtleUFydE9uU2FsZQAAAAIFAAAADGFkZHJlc3NUb1VzZQUAAAAFYXJ0SWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAACmtleUFydEZsYWcAAAACBQAAAARhZGRyBQAAAAVhcnRJZAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACAgAAAA5sYXN0X2ludm9rZV9pZAUAAAACaWQJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQkBAAAAEWtleUFydE93bmVyQnlIYXNoAAAAAQUAAAAKc2hhMjU2SGFzaAkABEwAAAACCQEAAAALRGVsZXRlRW50cnkAAAABCQEAAAATa2V5QXJ0QXJ0aWRCeVNpZ25pZAAAAAIFAAAADGFkZHJlc3NUb1VzZQUAAAAG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AAAADmdldFN0cmluZ0J5S2V5AAAAAQkBAAAAEGtleUFydERpc3BsYXlDaWQAAAACBQAAAAZpc3N1ZXIFAAAABWFydElkBAAAAAlleHBvcnRDSUQJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAAA9rZXlBcnRFeHBvcnRDaWQAAAACBQAAAAZpc3N1ZXIFAAAABWFydElkBAAAAApleHBvcnRIYXNoCQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABCQEAAAAQa2V5QXJ0RXhwb3J0SGFzaAAAAAIFAAAABmlzc3VlcgUAAAAFYXJ0SWQEAAAACmxpY2VuY2VDSUQJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAABBrZXlBcnRMaWNlbmNlQ2lkAAAAAgUAAAAGaXNzdWVyBQAAAAVhcnRJZAQAAAALbGljZW5jZUhhc2gJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAABFrZXlBcnRMaWNlbmNlSGFzaAAAAAIFAAAABmlzc3VlcgUAAAAFYXJ0SWQEAAAAC2Rlc2NyaXB0aW9uCQABLwAAAAIJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAAAprZXlBcnREZXNjAAAAAgUAAAAGaXNzdWVyBQAAAAVhcnRJZAAAAAAAAAAAMgQAAAAKYW1vdW50U29sZAkBAAAAD2dldEludGVnZXJCeUtleQAAAAEJAQAAAAxrZXlBcnRJc3N1ZWQAAAACBQAAAAZpc3N1ZXIFAAAABWFydElkBAAAAAxhcnR3b3JrUHJpY2UJAQAAAA9nZXRJbnRlZ2VyQnlLZXkAAAABCQEAAAALa2V5QXJ0UHJpY2UAAAACBQAAAAZpc3N1ZXIFAAAABWFydElkBAAAAAhpc09uU2FsZQkBAAAAD2dldEJvb2xlYW5CeUtleQAAAAEJAQAAAAxrZXlBcnRPblNhbGUAAAACBQAAAAZpc3N1ZXIFAAAABWFydElkBAAAAAxwcmljZUFzc2V0SWQJAQAAAA5nZXRTdHJpbmdCeUtleQAAAAEJAQAAABVrZXlBcnRBc3NldElkQWNjZXB0ZWQAAAACBQAAAAZpc3N1ZXIFAAAABWFydElkBAAAAApzb3VyY2VIYXNoCQEAAAAOZ2V0U3RyaW5nQnlLZXkAAAABCQEAAAAUa2V5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", "height": 1281874, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 5m16hwuHsPFxe1gqyuCvQqhahKSNoNUZsyaLYjUUCLuq Next: 5pwAF1BVazhFmgu1fBksobKpT7XPtcwMr7rBQQnhbrtY Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 4 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let storageVerifier = value(addressFromString("3N2s5RtaHPBenCsx2ECcoFRbYHx3noZhXW1"))
4+let oracleFee = value(addressFromString("3N2s5RtaHPBenCsx2ECcoFRbYHx3noZhXW1"))
55
6-let signVerifier = value(addressFromString("3NC28hSivrmsTUXaYD1x6L362J4ZpUnoTdB"))
6+let signDapp = value(addressFromString("3NC28hSivrmsTUXaYD1x6L362J4ZpUnoTdB"))
77
88 let feeReceiver = "3N1E6tXddRoVaRfQ9dQ3vg5LaW2fsd8HKub"
99
1010 let signAssetId = base58'Gf9t8FA4H3ssoZPCwrg3KwUFCci8zuUFP9ssRsUY3s6a'
1111
12-let usdnID = "3KFXBGGLCjA5Z2DuW4Dq9fDDrHjJJP1ZEkaoajSzuKsC"
12+let usdnAssetId = base58'25FEqEjRkqK6yCkiT7Lz6SAYz7gUFCtxfCChnrVFD5AT'
1313
14-let admin = "3MsG6jPNCrVJUtYB7XJBxS7utWsXAf4n9Vp"
14+let wavesAssetId = base58''
1515
16-let admin2 = "3Mzm4VLwsN9uZwbTMzPj3XuxV6kEfAR8UDN"
16+let signCut = 8
17+
18+let usdnCut = 10
19+
20+let wavesCut = 10
21+
22+let chris = "3MsG6jPNCrVJUtYB7XJBxS7utWsXAf4n9Vp"
23+
24+let joep = "3Mzm4VLwsN9uZwbTMzPj3XuxV6kEfAR8UDN"
1725
1826 let WHITELISTEDONLY = true
27+
28+let dappRunning = true
29+
30+let maintenanceMSG = "SIGN Art is under maintenance"
1931
2032 let userAllowed = "ALLOWED"
2133
2739
2840 let userRemoved = "REMOVED"
2941
42+let userChangeRequired = "CHANGE_REQUIRED"
43+
3044 let userUnregistered = "UNREGISTERED"
3145
32-let onSale = "ON_SALE"
33-
34-let sold = "SOLD"
35-
36-let canceled = "CANCELED"
46+let userReset = "RESET"
3747
3848 func getStringByKey (key) = match getString(this, key) {
3949 case a: String =>
4050 a
4151 case _ =>
4252 ""
53+}
54+
55+
56+func getIntegerByKeyFromOracle (key) = match getInteger(oracleFee, key) {
57+ case a: Int =>
58+ a
59+ case _ =>
60+ throw("Integer undefine or 0 in oracle")
4361 }
4462
4563
5169 }
5270
5371
54-func checkSignCertificate (signID,Owner,sha256Hash) = match getString(signVerifier, ((("data_fc_" + signID) + "_") + Owner)) {
72+func getBooleanByKey (key) = match getBoolean(this, key) {
73+ case i: Boolean =>
74+ i
75+ case _ =>
76+ false
77+}
78+
79+
80+func checkSignCertificate (signID,Owner,sha256Hash) = match getString(signDapp, ((("data_fc_" + signID) + "_") + Owner)) {
5581 case a: String =>
5682 if (contains(a, sha256Hash))
5783 then true
6187 }
6288
6389
64-func validateNFTs (accumulator,id) = {
65- let assetDetails = value(assetInfo(fromBase58String(id)))
66- if (if (if ((assetDetails.quantity != 1))
67- then true
68- else (assetDetails.decimals != 0))
69- then true
70- else (assetDetails.reissuable != false))
71- then (accumulator + 0)
72- else (accumulator + 1)
73- }
90+func validateCID (cid) = if (if ((75 > size(cid)))
91+ then (60 > size(split(cid, "/")[0]))
92+ else false)
93+ then (16 > size(split(cid, "/")[1]))
94+ else false
7495
7596
76-func verifyStatus (addr) = match getString(this, ("user_status_" + addr)) {
77- case b: String =>
78- b
79- case _ =>
80- throw("Something went wrong.")
81-}
97+func validateHash (hash) = (65 > size(hash))
8298
8399
84-func keyUserAddr (callerAddr) = ("user_" + callerAddr)
100+func keyUserAddr (caller) = ("user_" + caller)
85101
86102
87-func keyUserName (callerAddr) = ("user_name_" + callerAddr)
103+func keyUserName (caller) = ("user_name_" + caller)
88104
89105
90-func keyUserDesc (callerAddr) = ("user_desc_" + callerAddr)
106+func keyUserDesc (caller) = ("user_desc_" + caller)
91107
92108
93-func keyUserSocial (callerAddr) = ("user_social_" + callerAddr)
109+func keyUserSocial (caller) = ("user_social_" + caller)
94110
95111
96-func keyUserThumb (callerAddr) = ("user_thumb_" + callerAddr)
112+func keyUserThumb (caller) = ("user_thumb_" + caller)
97113
98114
99-func keyUserStatus (callerAddr) = ("user_status_" + callerAddr)
115+func keyUserStatus (caller) = ("user_status_" + caller)
100116
101117
102-func keyUserDate (callerAddr) = ("user_date_" + callerAddr)
118+func keyUserDate (caller) = ("user_date_" + caller)
103119
104120
105-func keyArtDate (callerAddr,artId) = ((("art_date_" + artId) + "_") + callerAddr)
121+func keyArtDate (caller,artId) = ((("art_date_" + artId) + "_") + caller)
106122
107123
108-func keyArtName (callerAddr,artId) = ((("art_name_" + artId) + "_") + callerAddr)
124+func keyArtName (caller,artId) = ((("art_name_" + artId) + "_") + caller)
109125
110126
111-func keyArtDesc (callerAddr,artId) = ((("art_desc_" + artId) + "_") + callerAddr)
127+func keyArtDesc (caller,artId) = ((("art_desc_" + artId) + "_") + caller)
112128
113129
114-func keyArtDisplayCid (callerAddr,artId) = ((("art_display_cid_" + artId) + "_") + callerAddr)
130+func keyArtDisplayCid (caller,artId) = ((("art_display_cid_" + artId) + "_") + caller)
115131
116132
117-func keyArtExportHash (callerAddr,artId) = ((("art_export_hash_" + artId) + "_") + callerAddr)
133+func keyArtExportHash (caller,artId) = ((("art_export_hash_" + artId) + "_") + caller)
118134
119135
120-func keyArtExportCid (callerAddr,artId) = ((("art_export_cid_" + artId) + "_") + callerAddr)
136+func keyArtExportCid (caller,artId) = ((("art_export_cid_" + artId) + "_") + caller)
121137
122138
123-func keyArtMaxMint (callerAddr,artId) = ((("art_maxmint_" + artId) + "_") + callerAddr)
139+func keyArtMaxMint (caller,artId) = ((("art_maxmint_" + artId) + "_") + caller)
124140
125141
126-func keyArtSignID (callerAddr,artId) = ((("art_signid_" + artId) + "_") + callerAddr)
142+func keyArtSignID (caller,artId) = ((("art_signid_" + artId) + "_") + caller)
127143
128144
129-func keyArtIssued (callerAddr,artId) = ((("art_issued_" + artId) + "_") + callerAddr)
145+func keyArtIssued (caller,artId) = ((("art_issued_" + artId) + "_") + caller)
130146
131147
132-func keyArtOnSale (callerAddr,artId) = ((("art_onsale_" + artId) + "_") + callerAddr)
148+func keyArtOnSale (caller,artId) = ((("art_onsale_" + artId) + "_") + caller)
133149
134150
135-func keyArtLicenceHash (callerAddr,artId) = ((("art_licence_hash_" + artId) + "_") + callerAddr)
151+func keyArtLicenceHash (caller,artId) = ((("art_licence_hash_" + artId) + "_") + caller)
136152
137153
138-func keyArtLicenceCid (callerAddr,artId) = ((("art_licence_cid_" + artId) + "_") + callerAddr)
154+func keyArtLicenceCid (caller,artId) = ((("art_licence_cid_" + artId) + "_") + caller)
139155
140156
141-func keyArtTags (callerAddr,artId) = ((("art_tags_" + artId) + "_") + callerAddr)
157+func keyArtTags (caller,artId) = ((("art_tags_" + artId) + "_") + caller)
142158
143159
144-func keyArtType (callerAddr,artId) = ((("art_type_" + artId) + "_") + callerAddr)
160+func keyArtType (caller,artId) = ((("art_type_" + artId) + "_") + caller)
145161
146162
147-func keyArtHashByTxidAddr (callerAddr,txid) = ((("get_hashbytxidaddr_" + txid) + "_") + callerAddr)
163+func keyArtPrice (caller,artId) = ((("art_price_" + artId) + "_") + caller)
164+
165+
166+func keyArtAssetIdAccepted (caller,artId) = ((("art_assetAccepted_" + artId) + "_") + caller)
167+
168+
169+func keyArtFlag (caller,artId) = ((("art_flag_" + artId) + "_") + caller)
170+
171+
172+func keyArtHashByTxidAddr (caller,txid) = ((("get_hashbytxidaddr_" + txid) + "_") + caller)
148173
149174
150175 func keyArtOwnerByHash (sha256Hash) = ("get_owner_by_hash_" + sha256Hash)
151176
152177
153-func keyArtArtidBySignid (callerAddr,signId) = ((("get_artidbysignid_" + signId) + "_") + callerAddr)
178+func keyArtArtidBySignid (caller,signId) = ((("get_artidbysignid_" + signId) + "_") + caller)
154179
155180
156-func keyArtTxidByHashOwner (sha256Hash,callerAddr) = ("get_txid_by_hash_owner_" + toBase58String(sha256_16Kb(toBytes((sha256Hash + callerAddr)))))
181+func keyArtTxidByHashOwner (sha256Hash,caller) = ("get_txid_by_hash_owner_" + toBase58String(sha256_16Kb(toBytes((sha256Hash + caller)))))
182+
183+
184+func validateAllCID (cidDisplay,cidExport,cidLicence) = if (if ((cidDisplay != ""))
185+ then !(validateCID(cidDisplay))
186+ else false)
187+ then throw("Wrong Display CID")
188+ else if (if ((cidExport != ""))
189+ then !(validateCID(cidExport))
190+ else false)
191+ then throw("Wrong Export CID")
192+ else if (if ((cidLicence != ""))
193+ then !(validateCID(cidLicence))
194+ else false)
195+ then throw("Wrong Licence CID")
196+ else true
197+
198+
199+func validateAllHash (sha256Export,sha256Licence) = if (if ((sha256Export != ""))
200+ then !(validateHash(sha256Export))
201+ else false)
202+ then throw("Export Hash 64 char. max")
203+ else if (if ((sha256Licence != ""))
204+ then !(validateHash(sha256Licence))
205+ else false)
206+ then throw("Licence Hash 64 char. max")
207+ else true
208+
209+
210+func validateString (str,max) = if ((size(str) == 0))
211+ then throw("Field cannot be is empty")
212+ else if ((size(str) > max))
213+ then throw((str + " is too long"))
214+ else true
157215
158216
159217 @Callable(i)
160-func registerUser (name,description,thumb,social) = {
161- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
162- let userCanRegister = getStringByKey(keyUserStatus(callerAddr))
163- let id = toBase58String(i.transactionId)
164- let timestamp = lastBlock.timestamp
165- if (if ((userCanRegister == userSuspended))
166- then true
167- else (userCanRegister == userRemoved))
168- then throw("You are now allowed to register, your account have been suspended/ removed.")
169- else if ((userCanRegister == userRegistered))
170- then throw("You are already registered, please use update method instead.")
171- else if (if ((userCanRegister == ""))
172- then WHITELISTEDONLY
173- else false)
174- then throw("You are now allowed to register yet, please contact us first to get approved.")
218+func registerUser (name,description,thumb,social) = if (!(dappRunning))
219+ then throw(maintenanceMSG)
220+ else {
221+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
222+ let canRegister = getStringByKey(keyUserStatus(caller))
223+ let id = toBase58String(i.transactionId)
224+ let timestamp = lastBlock.timestamp
225+ if (if ((canRegister == userSuspended))
226+ then true
227+ else (canRegister == userRemoved))
228+ then throw("Account suspended/ removed.")
229+ else if ((canRegister == userRegistered))
230+ then throw("Already registered")
231+ else if (if ((canRegister == ""))
232+ then WHITELISTEDONLY
233+ else false)
234+ then throw("Can't register, get approved first.")
235+ else if (if ((name == ""))
236+ then true
237+ else (description == ""))
238+ then throw("Name and description cannot be empty")
239+ else if ((size(description) > 600))
240+ then throw("600 Char. max description")
241+ else if ((size(name) > 45))
242+ then throw("45 Char. max name")
243+ else [IntegerEntry(keyUserDate(caller), timestamp), StringEntry(keyUserAddr(caller), ((id + "_") + toString(timestamp))), StringEntry(keyUserName(caller), name), StringEntry(keyUserDesc(caller), description), StringEntry(keyUserSocial(caller), social), StringEntry(keyUserThumb(caller), thumb), StringEntry(keyUserStatus(caller), userRegistered), StringEntry("last_invoke_id", id)]
244+ }
245+
246+
247+
248+@Callable(i)
249+func updateUser (name,description,thumb,social) = if (!(dappRunning))
250+ then throw(maintenanceMSG)
251+ else {
252+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
253+ let id = toBase58String(i.transactionId)
254+ let canUpdate = getStringByKey(keyUserStatus(caller))
255+ if (if ((canUpdate == userSuspended))
256+ then true
257+ else (canUpdate == userRemoved))
258+ then throw("Account suspended/ removed.")
259+ else if (if ((canUpdate == ""))
260+ then true
261+ else (canUpdate == userAllowed))
262+ then throw("Register first")
175263 else if (if ((name == ""))
176264 then true
177265 else (description == ""))
178- then throw("Name and description cannot be empty")
266+ then throw("Name & description cannot be empty")
179267 else if ((size(description) > 600))
180- then throw("600 Characters maximum for the description")
181- else [IntegerEntry(keyUserDate(callerAddr), timestamp), StringEntry(keyUserAddr(callerAddr), ((id + "_") + toString(lastBlock.timestamp))), StringEntry(keyUserName(callerAddr), name), StringEntry(keyUserDesc(callerAddr), description), StringEntry(keyUserSocial(callerAddr), social), StringEntry(keyUserThumb(callerAddr), thumb), StringEntry(keyUserStatus(callerAddr), userRegistered), StringEntry("last_invoke_id", id)]
268+ then throw("600 Char. max for description")
269+ else if ((size(name) > 45))
270+ then throw("45 Char. max name")
271+ else [StringEntry(keyUserName(caller), name), StringEntry(keyUserDesc(caller), description), StringEntry(keyUserSocial(caller), social), StringEntry(keyUserThumb(caller), thumb), StringEntry("last_invoke_id", id)]
272+ }
273+
274+
275+
276+@Callable(i)
277+func changeUserStatus (address,status) = if (!(dappRunning))
278+ then throw(maintenanceMSG)
279+ else {
280+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
281+ let id = toBase58String(i.transactionId)
282+ let currentStatus = getStringByKey(keyUserStatus(address))
283+ let statusToSet = if ((status == userVerified))
284+ then userVerified
285+ else if ((status == userRegistered))
286+ then userRegistered
287+ else if ((status == userSuspended))
288+ then userSuspended
289+ else if ((status == userRemoved))
290+ then userRemoved
291+ else if ((status == userAllowed))
292+ then userAllowed
293+ else if ((status == userChangeRequired))
294+ then userChangeRequired
295+ else if (if ((status == userReset))
296+ then (currentStatus == userAllowed)
297+ else false)
298+ then ""
299+ else throw("Unknown status")
300+ if (if ((currentStatus == userAllowed))
301+ then (status == userAllowed)
302+ else false)
303+ then throw("User already allowed")
304+ else if (if ((currentStatus == userRegistered))
305+ then (status == userAllowed)
306+ else false)
307+ then throw("User already allowed & registered")
308+ else if (if ((currentStatus == userVerified))
309+ then (status == userAllowed)
310+ else false)
311+ then throw("User already allowed & verified")
312+ else if (containsElement([chris, joep], caller))
313+ then [StringEntry(keyUserStatus(address), statusToSet), StringEntry("last_invoke_id", id)]
314+ else throw(((("Not allowed to change user status " + caller) + " / ") + chris))
315+ }
316+
317+
318+
319+@Callable(invoke)
320+func addArtwork (sha256Hash,signID,name,description,tags,type,maxmint,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence) = if (!(dappRunning))
321+ then throw(maintenanceMSG)
322+ else {
323+ let artId = toBase58String(invoke.transactionId)
324+ let caller = toBase58String(invoke.caller.bytes)
325+ if (!(validateAllCID(cidDisplay, cidExport, cidLicence)))
326+ then throw("Problem with CID")
327+ else if (!(validateHash(sha256Hash)))
328+ then throw("Hash should be 64 characters maximum")
329+ else if (!(validateAllHash(sha256Export, sha256Licence)))
330+ then throw("Problem with Hashes")
331+ else if ((size(invoke.payments) == 0))
332+ then throw("No payment attached")
333+ else {
334+ let payment = value(invoke.payments[0])
335+ let amount = value(payment.amount)
336+ let assetId = if (if (isDefined(payment.assetId))
337+ then (payment.assetId == signAssetId)
338+ else false)
339+ then payment.assetId
340+ else throw("Only SIGN token accepted at the moment")
341+ let currentCertificationPrice = getIntegerByKeyFromOracle(("certification_fee_" + toBase58String(signAssetId)))
342+ if ((amount != currentCertificationPrice))
343+ then throw(("Payment amount should be " + toString(currentCertificationPrice)))
344+ else {
345+ let entryExist = getStringByKey(keyArtTxidByHashOwner(sha256Hash, caller))
346+ if ((entryExist != ""))
347+ then throw("You already added it")
348+ else {
349+ let hashExist = getStringByKey(keyArtOwnerByHash(sha256Hash))
350+ if ((hashExist != ""))
351+ then throw("Hash already registered")
352+ else {
353+ let isSignCertified = checkSignCertificate(signID, caller, sha256Hash)
354+ if (!(isSignCertified))
355+ then throw("Sign Certificate not found for this address.")
356+ else if ((size(cidDisplay) == 0))
357+ then throw("Display CID cannot be empty")
358+ else if (!(validateString(name, 100)))
359+ then throw("100 Char. max name")
360+ else if (!(validateString(description, 1000)))
361+ then throw("1000 Char. max description")
362+ else if ((size(split(tags, ",")) > 5))
363+ then throw("5 tags max.")
364+ else {
365+ let userIsRegistered = match getString(this, ("user_status_" + caller)) {
366+ case s: String =>
367+ s
368+ case _ =>
369+ userUnregistered
370+ }
371+ let timestamp = lastBlock.timestamp
372+ if (if (isDefined(userIsRegistered))
373+ then (userIsRegistered == userUnregistered)
374+ else false)
375+ then throw("Register this account first with \"User infos\" tab")
376+ else if ((userIsRegistered == userSuspended))
377+ then throw("Account suspended")
378+ else if ((userIsRegistered == userRemoved))
379+ then throw("Account removed")
380+ else if ((maxmint > 10))
381+ then throw("10 editions max")
382+ else if ((size(sha256Hash) != 64))
383+ then throw("Hash 64 char. max")
384+ else [StringEntry(keyArtOwnerByHash(sha256Hash), caller), StringEntry(keyArtTxidByHashOwner(sha256Hash, caller), artId), IntegerEntry(keyArtDate(caller, artId), timestamp), StringEntry(keyArtName(caller, artId), name), StringEntry(keyArtDesc(caller, artId), description), StringEntry(keyArtDisplayCid(caller, artId), cidDisplay), StringEntry(keyArtExportCid(caller, artId), cidExport), StringEntry(keyArtExportHash(caller, artId), sha256Export), StringEntry(keyArtLicenceHash(caller, artId), sha256Licence), StringEntry(keyArtLicenceCid(caller, artId), cidLicence), StringEntry(keyArtType(caller, artId), type), StringEntry(keyArtTags(caller, artId), tags), IntegerEntry(keyArtMaxMint(caller, artId), maxmint), StringEntry(keyArtSignID(caller, artId), signID), IntegerEntry(keyArtIssued(caller, artId), 0), BooleanEntry(keyArtOnSale(caller, artId), false), StringEntry(keyArtArtidBySignid(caller, signID), artId), StringEntry("last_invoke_id", artId), StringEntry(keyArtHashByTxidAddr(caller, artId), sha256Hash), ScriptTransfer(Address(fromBase58String(feeReceiver)), amount, assetId)]
385+ }
386+ }
387+ }
388+ }
389+ }
390+ }
391+
392+
393+
394+@Callable(invoke)
395+func updateArtwork (txid,name,description,tags,type,maxmint,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence) = if (!(dappRunning))
396+ then throw(maintenanceMSG)
397+ else {
398+ let updateId = toBase58String(invoke.transactionId)
399+ let caller = toBase58String(invoke.caller.bytes)
400+ if (!(validateAllCID(cidDisplay, cidExport, cidLicence)))
401+ then throw("Problem with CID")
402+ else if (!(validateAllHash(sha256Export, sha256Licence)))
403+ then throw("Problem with Hashes")
404+ else {
405+ let entryExist = getStringByKey(keyArtName(caller, txid))
406+ if ((entryExist == ""))
407+ then throw("Entry not found")
408+ else if (!(validateString(name, 100)))
409+ then throw("100 Char. max name")
410+ else if (!(validateString(description, 1000)))
411+ then throw("1000 Char. max description")
412+ else {
413+ let flag = getStringByKey(keyArtFlag(caller, txid))
414+ if ((flag == "ILLEGAL"))
415+ then throw("Cannot update")
416+ else {
417+ let artworkMinted = match getInteger(this, keyArtIssued(caller, txid)) {
418+ case b: Int =>
419+ if ((b == 0))
420+ then false
421+ else true
422+ case _ =>
423+ false
424+ }
425+ if ((size(split(tags, ",")) > 5))
426+ then throw("5 tags max.")
427+ else {
428+ let userIsRegistered = match getString(this, ("user_status_" + caller)) {
429+ case s: String =>
430+ s
431+ case _ =>
432+ userUnregistered
433+ }
434+ if (if (isDefined(userIsRegistered))
435+ then (userIsRegistered == userUnregistered)
436+ else false)
437+ then throw("Register first with \"User infos\"")
438+ else if ((userIsRegistered == userSuspended))
439+ then throw("Account suspended")
440+ else if ((userIsRegistered == userRemoved))
441+ then throw("Account removed")
442+ else if ((maxmint > 10))
443+ then throw("10 editions max per artwork")
444+ else if (!(artworkMinted))
445+ then [StringEntry(keyArtName(caller, txid), name), StringEntry(keyArtDesc(caller, txid), description), StringEntry(keyArtDisplayCid(caller, txid), cidDisplay), StringEntry(keyArtExportCid(caller, txid), cidExport), StringEntry(keyArtExportHash(caller, txid), sha256Export), StringEntry(keyArtLicenceCid(caller, txid), cidLicence), StringEntry(keyArtLicenceHash(caller, txid), sha256Licence), IntegerEntry(keyArtMaxMint(caller, txid), maxmint), StringEntry(keyArtTags(caller, txid), tags), StringEntry(keyArtType(caller, txid), type), StringEntry("last_invoke_id", updateId)]
446+ else throw("Already minted")
447+ }
448+ }
449+ }
450+ }
451+ }
452+
453+
454+
455+@Callable(i)
456+func flagArtwork (artId,addr,flag) = {
457+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
458+ let id = toBase58String(i.transactionId)
459+ if (containsElement([chris, joep], caller))
460+ then if ((flag == "CONSENT"))
461+ then [StringEntry(keyArtFlag(addr, artId), flag), StringEntry("last_invoke_id", id)]
462+ else if ((flag == ""))
463+ then [StringEntry(keyArtFlag(addr, artId), flag), StringEntry("last_invoke_id", id)]
464+ else if ((flag == "ILLEGAL"))
465+ then [StringEntry(keyArtFlag(addr, artId), flag), StringEntry(keyArtName(addr, artId), "ILLEGAL CONTENT"), StringEntry(keyArtDesc(addr, artId), "ILLEGAL CONTENT"), StringEntry(keyArtDisplayCid(addr, artId), ""), StringEntry(keyArtExportCid(addr, artId), ""), StringEntry(keyArtLicenceCid(addr, artId), ""), StringEntry("last_invoke_id", id)]
466+ else throw(("Unknow status" + flag))
467+ else throw("no")
468+ }
469+
470+
471+
472+@Callable(i)
473+func deleteArtwork (artId,addr) = {
474+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
475+ let id = toBase58String(i.transactionId)
476+ let addressToUse = if (containsElement([chris, joep], caller))
477+ then addr
478+ else caller
479+ let entryExist = match getString(this, keyArtName(addressToUse, artId)) {
480+ case s: String =>
481+ s
482+ case _ =>
483+ throw("No art matching")
484+ }
485+ let artworkMinted = match getInteger(this, keyArtIssued(addressToUse, artId)) {
486+ case b: Int =>
487+ if ((b != 0))
488+ then true
489+ else false
490+ case _ =>
491+ false
492+ }
493+ let maxMint = getIntegerByKey(keyArtMaxMint(addressToUse, artId))
494+ let sha256Hash = match getString(this, keyArtHashByTxidAddr(addressToUse, artId)) {
495+ case s: String =>
496+ s
497+ case _ =>
498+ throw("No art hash matching")
499+ }
500+ let signID = match getString(this, keyArtSignID(addressToUse, artId)) {
501+ case s: String =>
502+ s
503+ case _ =>
504+ throw("No SIGN ID matching")
505+ }
506+ let dataToDelete = [DeleteEntry(keyArtDate(addressToUse, artId)), DeleteEntry(keyArtName(addressToUse, artId)), DeleteEntry(keyArtDesc(addressToUse, artId)), DeleteEntry(keyArtDisplayCid(addressToUse, artId)), DeleteEntry(keyArtExportCid(addressToUse, artId)), DeleteEntry(keyArtExportHash(addressToUse, artId)), DeleteEntry(keyArtLicenceHash(addressToUse, artId)), DeleteEntry(keyArtLicenceCid(addressToUse, artId)), DeleteEntry(keyArtType(addressToUse, artId)), DeleteEntry(keyArtTags(addressToUse, artId)), DeleteEntry(keyArtMaxMint(addressToUse, artId)), DeleteEntry(keyArtSignID(addressToUse, artId)), DeleteEntry(keyArtIssued(addressToUse, artId)), DeleteEntry(keyArtOnSale(addressToUse, artId)), DeleteEntry(keyArtFlag(addr, artId)), StringEntry("last_invoke_id", id), DeleteEntry(keyArtOwnerByHash(sha256Hash)), DeleteEntry(keyArtArtidBySignid(addressToUse, signID)), DeleteEntry(keyArtTxidByHashOwner(sha256Hash, addressToUse))]
507+ if (!(artworkMinted))
508+ then if (!(dappRunning))
509+ then throw(maintenanceMSG)
510+ else dataToDelete
511+ else throw("Art already minted, cannot delete")
512+ }
513+
514+
515+
516+@Callable(i)
517+func sellArtwork (artId,price,maxMint,assetId) = if (!(dappRunning))
518+ then throw(maintenanceMSG)
519+ else {
520+ let id = toBase58String(i.transactionId)
521+ let caller = toBase58String(i.caller.bytes)
522+ let sellDate = lastBlock.timestamp
523+ let exportCID = getStringByKey(keyArtExportCid(caller, artId))
524+ if ((size(split(exportCID, "/")[0]) != 59))
525+ then throw("You cannot sell art with no export file")
526+ else {
527+ let exportHash = getStringByKey(keyArtExportHash(caller, artId))
528+ if ((size(exportHash) != 64))
529+ then throw("You cannot sell art with no export hash")
530+ else if (if (if ((assetId != toBase58String(signAssetId)))
531+ then (assetId != toBase58String(wavesAssetId))
532+ else false)
533+ then (assetId != toBase58String(usdnAssetId))
534+ else false)
535+ then throw("Only SIGN, USDN or WAVES accepted")
536+ else {
537+ let minSellWaves = getIntegerByKeyFromOracle("waves_min_sell")
538+ let minSellUsdn = 1000000
539+ let minSellSign = (getIntegerByKeyFromOracle(("certification_fee_" + toBase58String(signAssetId))) * 2)
540+ if (if (if (if (if ((assetId == toBase58String(usdnAssetId)))
541+ then (minSellUsdn > price)
542+ else false)
543+ then (price != 0)
544+ else false)
545+ then true
546+ else if (if ((assetId == toBase58String(signAssetId)))
547+ then (minSellSign > price)
548+ else false)
549+ then (price != 0)
550+ else false)
551+ then true
552+ else if (if ((assetId == toBase58String(wavesAssetId)))
553+ then (minSellWaves > price)
554+ else false)
555+ then (price != 0)
556+ else false)
557+ then throw("Wrong minimum sell price")
558+ else {
559+ let artworkName = match getString(this, keyArtName(caller, artId)) {
560+ case s: String =>
561+ s
562+ case _ =>
563+ throw("This art doesn't match")
564+ }
565+ let userIsRegistered = match getString(this, keyUserStatus(caller)) {
566+ case s: String =>
567+ s
568+ case _ =>
569+ throw("Register this account first")
570+ }
571+ let amountSold = getIntegerByKey(keyArtIssued(caller, artId))
572+ let maxCanSell = getIntegerByKey(keyArtMaxMint(caller, artId))
573+ if (if ((amountSold != 0))
574+ then (amountSold == maxCanSell)
575+ else false)
576+ then throw("Max edition reached.")
577+ else if (if ((amountSold > 0))
578+ then (maxCanSell != maxMint)
579+ else false)
580+ then throw("Cannot change maximum issuable anymore")
581+ else if ((userIsRegistered == userSuspended))
582+ then throw("Account suspended")
583+ else if ((userIsRegistered == userRemoved))
584+ then throw("Account deleted")
585+ else {
586+ let sellStatus = if (if ((price > 0))
587+ then (maxMint > 0)
588+ else false)
589+ then true
590+ else false
591+[BooleanEntry(keyArtOnSale(caller, artId), sellStatus), IntegerEntry(keyArtPrice(caller, artId), price), IntegerEntry(keyArtMaxMint(caller, artId), maxMint), StringEntry(keyArtAssetIdAccepted(caller, artId), assetId), StringEntry("last_invoke_id", id)]
592+ }
593+ }
594+ }
595+ }
596+ }
597+
598+
599+
600+@Callable(i)
601+func buyArtwork (artId,issuer) = if (!(dappRunning))
602+ then throw(maintenanceMSG)
603+ else {
604+ let id = toBase58String(i.transactionId)
605+ let caller = toBase58String(i.caller.bytes)
606+ let totalNFT = getIntegerByKey("total_nft_issued")
607+ let signID = getStringByKey(keyArtSignID(issuer, artId))
608+ let artworkName = match getString(this, keyArtName(issuer, artId)) {
609+ case s: String =>
610+ s
611+ case _ =>
612+ throw("Art doesn't exist")
613+ }
614+ let displayCID = getStringByKey(keyArtDisplayCid(issuer, artId))
615+ let exportCID = getStringByKey(keyArtExportCid(issuer, artId))
616+ let exportHash = getStringByKey(keyArtExportHash(issuer, artId))
617+ let licenceCID = getStringByKey(keyArtLicenceCid(issuer, artId))
618+ let licenceHash = getStringByKey(keyArtLicenceHash(issuer, artId))
619+ let description = take(getStringByKey(keyArtDesc(issuer, artId)), 50)
620+ let amountSold = getIntegerByKey(keyArtIssued(issuer, artId))
621+ let artworkPrice = getIntegerByKey(keyArtPrice(issuer, artId))
622+ let isOnSale = getBooleanByKey(keyArtOnSale(issuer, artId))
623+ let priceAssetId = getStringByKey(keyArtAssetIdAccepted(issuer, artId))
624+ let sourceHash = getStringByKey(keyArtHashByTxidAddr(issuer, artId))
625+ if ((artworkPrice == 0))
626+ then throw("Art not for sell")
627+ else if (!(isOnSale))
628+ then throw("Art not for sale")
629+ else {
630+ let maxCanSell = getIntegerByKey(keyArtMaxMint(issuer, artId))
631+ let payment = value(i.payments[0])
632+ let amount = value(payment.amount)
633+ let assetId = if (if (if (isDefined(payment.assetId))
634+ then (size(fromBase58String(priceAssetId)) > 0)
635+ else false)
636+ then (payment.assetId == fromBase58String(priceAssetId))
637+ else false)
638+ then payment.assetId
639+ else unit
640+ let cut = if ((priceAssetId == toBase58String(signAssetId)))
641+ then 8
642+ else 10
643+ let amountForSign = fraction(amount, cut, 100)
644+ let amountForCreator = (amount - amountForSign)
645+ if ((amountSold == maxCanSell))
646+ then throw("Art sold out")
647+ else if ((artworkPrice != amount))
648+ then throw("Payment don't match")
649+ else {
650+ let newAmountSold = (amountSold + 1)
651+ let entryDate = lastBlock.timestamp
652+ let issueMeta = ((((((((((((((((((((((((((("Creator: " + issuer) + ",
653+ ArtID: ") + artId) + ",
654+ SignID: ") + signID) + ",
655+ Artwork name: ") + artworkName) + ",
656+ Artwork description: ") + description) + ",
657+ Issue: ") + toString(newAmountSold)) + "/") + toString(maxCanSell)) + ",
658+ Max issuable: ") + toString(maxCanSell)) + ",
659+ Source hash: ") + sourceHash) + ",
660+ Display cid: ") + displayCID) + ",
661+ Export cid: ") + exportCID) + ",
662+ Export hash: ") + exportHash) + ",
663+ Licence cid: ") + licenceCID) + ",
664+ Licence hash: ") + licenceHash)
665+ let issueNFT = Issue(("SA_" + toString((totalNFT + 1))), issueMeta, 1, 0, false)
666+ let idNFT = calculateAssetId(issueNFT)
667+ let sellStatus = if ((newAmountSold == maxCanSell))
668+ then false
669+ else true
670+[IntegerEntry(keyArtIssued(issuer, artId), newAmountSold), StringEntry(((((((("art_sold_" + toString(newAmountSold)) + "_of_") + toString(maxCanSell)) + "_") + artId) + "_") + issuer), ((((((((((caller + "_") + toString(entryDate)) + "_") + id) + "_") + toString(artworkPrice)) + "_") + priceAssetId) + "_") + toBase58String(idNFT))), IntegerEntry("total_nft_issued", (totalNFT + 1)), BooleanEntry(keyArtOnSale(issuer, artId), sellStatus), StringEntry("last_invoke_id", id), issueNFT, ScriptTransfer(Address(fromBase58String(issuer)), amountForCreator, assetId), ScriptTransfer(Address(fromBase58String(feeReceiver)), amountForSign, assetId), ScriptTransfer(i.caller, 1, idNFT)]
671+ }
672+ }
673+ }
674+
675+
676+
677+@Callable(i)
678+func creditUser (address) = {
679+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
680+ let id = toBase58String(i.transactionId)
681+ if (containsElement([chris, joep], caller))
682+ then [ScriptTransfer(Address(fromBase58String(address)), 150000000000, signAssetId)]
683+ else throw("Not allowed")
684+ }
685+
686+
687+
688+@Callable(i)
689+func deleteUser (address) = {
690+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
691+ let id = toBase58String(i.transactionId)
692+ if (containsElement([chris, joep], caller))
693+ then [DeleteEntry(keyUserDate(address)), DeleteEntry(keyUserAddr(address)), DeleteEntry(keyUserName(address)), DeleteEntry(keyUserDesc(address)), DeleteEntry(keyUserSocial(address)), DeleteEntry(keyUserThumb(address)), StringEntry(keyUserStatus(address), userRemoved), StringEntry("last_invoke_id", id)]
694+ else throw("Not allowed")
182695 }
183696
184697
185698
186699 @Callable(i)
187700 func deleteEntry (entry) = {
188- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
189- if ((callerAddr == admin))
701+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
702+ if ((caller == chris))
190703 then [DeleteEntry(entry)]
191704 else throw("no")
192- }
193-
194-
195-
196-@Callable(i)
197-func updateUser (name,description,thumb,social) = {
198- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
199- let userCanRegister = getStringByKey(keyUserStatus(callerAddr))
200- if (if ((userCanRegister == userSuspended))
201- then true
202- else (userCanRegister == userRemoved))
203- then throw("You are now allowed to register, your account have been suspended/ removed.")
204- else if (if ((userCanRegister == ""))
205- then true
206- else (userCanRegister == userAllowed))
207- then throw("Please register first with registerUser")
208- else {
209- let id = toBase58String(i.transactionId)
210- let timestamp = lastBlock.timestamp
211- if (if ((name == ""))
212- then true
213- else (description == ""))
214- then throw("Name and description cannot be empty")
215- else if ((size(description) > 600))
216- then throw("600 Characters maximum for the description")
217- else [StringEntry(keyUserName(callerAddr), name), StringEntry(keyUserDesc(callerAddr), description), StringEntry(keyUserSocial(callerAddr), social), StringEntry(keyUserThumb(callerAddr), thumb), StringEntry("last_invoke_id", id)]
218- }
219- }
220-
221-
222-
223-@Callable(i)
224-func changeUserStatus (address,status) = {
225- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
226- let id = toBase58String(i.transactionId)
227- let statusToSet = if ((status == userVerified))
228- then userVerified
229- else if ((status == userRegistered))
230- then userRegistered
231- else if ((status == userSuspended))
232- then userSuspended
233- else if ((status == userRemoved))
234- then userRemoved
235- else if ((status == userAllowed))
236- then userAllowed
237- else throw("Unknown status")
238- if (if ((callerAddr == admin))
239- then true
240- else (callerAddr == admin2))
241- then [StringEntry(keyUserStatus(address), statusToSet), StringEntry("last_invoke_id", id)]
242- else throw(((("You are not allowed to change user status " + callerAddr) + " / ") + admin))
243- }
244-
245-
246-
247-@Callable(i)
248-func creditUser (address) = {
249- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
250- let id = toBase58String(i.transactionId)
251- if (if ((callerAddr == admin))
252- then true
253- else (callerAddr == admin2))
254- then [ScriptTransfer(Address(fromBase58String(address)), 150000000000, signAssetId)]
255- else throw("You are not allowed to do that")
256- }
257-
258-
259-
260-@Callable(invoke)
261-func addArtwork (sha256Hash,signID,name,description,tags,type,maxmint,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence) = {
262- let artId = toBase58String(invoke.transactionId)
263- let callerAddress = toBase58String(invoke.caller.bytes)
264- if ((size(invoke.payments) == 0))
265- then throw("No payment attached")
266- else {
267- let payment = value(invoke.payments[0])
268- let amount = value(payment.amount)
269- let assetId = if (if (isDefined(payment.assetId))
270- then (payment.assetId == signAssetId)
271- else false)
272- then payment.assetId
273- else throw("Only SIGN token accepted at the moment")
274- let currentCertificationPrice = match getInteger(storageVerifier, ("certification_fee_" + toBase58String(signAssetId))) {
275- case price: Int =>
276- price
277- case _ =>
278- throw("Price undefined in oracle")
279- }
280- if ((amount != currentCertificationPrice))
281- then throw(("Payment amount should be " + toString(currentCertificationPrice)))
282- else {
283- let entryExist = getStringByKey(keyArtTxidByHashOwner(sha256Hash, callerAddress))
284- if ((entryExist != ""))
285- then throw("You already added this artwork on Sign Art")
286- else {
287- let hashExist = getStringByKey(keyArtOwnerByHash(sha256Hash))
288- if ((hashExist != ""))
289- then throw("This artwork hash is already registered on Sign Art")
290- else {
291- let isSignCertified = checkSignCertificate(signID, callerAddress, sha256Hash)
292- if (!(isSignCertified))
293- then throw("Sign Certificate not found on Sign-web.app smart contract for this address.")
294- else if ((size(cidDisplay) == 0))
295- then throw("Display CID cannot be empty")
296- else if ((size(name) == 0))
297- then throw("Title cannot be empty")
298- else if ((size(name) > 100))
299- then throw("100 Characters maximum for the name")
300- else if ((size(description) > 1000))
301- then throw("1000 Characters maximum for the description")
302- else if ((size(description) == 0))
303- then throw("Description cannot be empty")
304- else {
305- let tagsList = split(tags, ",")
306- if ((size(tagsList) > 5))
307- then throw("Tags should be maximum 5 single word separated by space.")
308- else {
309- let userIsRegistered = match getString(this, ("user_status_" + callerAddress)) {
310- case s: String =>
311- s
312- case _ =>
313- userUnregistered
314- }
315- let timestamp = lastBlock.timestamp
316- if (if (isDefined(userIsRegistered))
317- then (userIsRegistered == userUnregistered)
318- else false)
319- then throw("Please register this account first with \"User infos\" tab")
320- else if ((userIsRegistered == userSuspended))
321- then throw("Your account is suspended")
322- else if ((userIsRegistered == userRemoved))
323- then throw("Your account have been removed")
324- else if ((maxmint > 10))
325- then throw("Maximum 10 editions per artwork")
326- else if ((size(sha256Hash) != 64))
327- then throw("Hash should be sha256 string composed of 64 char.")
328- else [StringEntry(keyArtOwnerByHash(sha256Hash), callerAddress), StringEntry(keyArtTxidByHashOwner(sha256Hash, callerAddress), artId), IntegerEntry(keyArtDate(callerAddress, artId), timestamp), StringEntry(keyArtName(callerAddress, artId), name), StringEntry(keyArtDesc(callerAddress, artId), description), StringEntry(keyArtDisplayCid(callerAddress, artId), cidDisplay), StringEntry(keyArtExportCid(callerAddress, artId), cidExport), StringEntry(keyArtExportHash(callerAddress, artId), sha256Export), StringEntry(keyArtLicenceHash(callerAddress, artId), sha256Licence), StringEntry(keyArtLicenceCid(callerAddress, artId), cidLicence), StringEntry(keyArtType(callerAddress, artId), type), StringEntry(keyArtTags(callerAddress, artId), tags), IntegerEntry(keyArtMaxMint(callerAddress, artId), maxmint), StringEntry(keyArtSignID(callerAddress, artId), signID), IntegerEntry(keyArtIssued(callerAddress, artId), 0), BooleanEntry(keyArtOnSale(callerAddress, artId), false), StringEntry(keyArtArtidBySignid(callerAddress, signID), artId), StringEntry("last_invoke_id", artId), StringEntry(keyArtHashByTxidAddr(callerAddress, artId), sha256Hash), ScriptTransfer(Address(fromBase58String(feeReceiver)), amount, assetId)]
329- }
330- }
331- }
332- }
333- }
334- }
335- }
336-
337-
338-
339-@Callable(invoke)
340-func updateArtwork (txid,name,description,tags,type,maxmint,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence) = {
341- let updateId = toBase58String(invoke.transactionId)
342- let callerAddress = toBase58String(invoke.caller.bytes)
343- let entryExist = getStringByKey(keyArtName(callerAddress, txid))
344- if ((entryExist == ""))
345- then throw("This entry doesn't exist or you are not the owner")
346- else if ((size(name) == 0))
347- then throw("Title cannot be empty")
348- else if ((size(name) > 100))
349- then throw("100 Characters maximum for the name")
350- else if ((size(description) > 1000))
351- then throw("1000 Characters maximum for the description")
352- else if ((size(description) == 0))
353- then throw("Description cannot be empty")
354- else {
355- let artworkMinted = match getInteger(this, keyArtIssued(callerAddress, txid)) {
356- case b: Int =>
357- if ((b == 0))
358- then false
359- else true
360- case _ =>
361- false
362- }
363- let tagsList = split(tags, ",")
364- if ((size(tagsList) > 5))
365- then throw("Tags should be maximum 5 single word separated by space.")
366- else {
367- let userIsRegistered = match getString(this, ("user_status_" + callerAddress)) {
368- case s: String =>
369- s
370- case _ =>
371- userUnregistered
372- }
373- if (if (isDefined(userIsRegistered))
374- then (userIsRegistered == userUnregistered)
375- else false)
376- then throw("Please register this account first with \"User infos\" tab")
377- else if ((userIsRegistered == userSuspended))
378- then throw("Your account is suspended")
379- else if ((userIsRegistered == userRemoved))
380- then throw("Your account have been removed")
381- else if ((maxmint > 10))
382- then throw("Maximum 10 editions per artwork")
383- else if (!(artworkMinted))
384- then [StringEntry(keyArtName(callerAddress, txid), name), StringEntry(keyArtDesc(callerAddress, txid), description), StringEntry(keyArtDisplayCid(callerAddress, txid), cidDisplay), StringEntry(keyArtExportCid(callerAddress, txid), cidExport), StringEntry(keyArtExportHash(callerAddress, txid), sha256Export), StringEntry(keyArtLicenceCid(callerAddress, txid), cidLicence), StringEntry(keyArtLicenceHash(callerAddress, txid), sha256Licence), IntegerEntry(keyArtMaxMint(callerAddress, txid), maxmint), StringEntry(keyArtTags(callerAddress, txid), tags), StringEntry(keyArtType(callerAddress, txid), type), StringEntry("last_invoke_id", updateId)]
385- else [StringEntry(keyArtName(callerAddress, txid), name), StringEntry(keyArtDesc(callerAddress, txid), description), StringEntry(keyArtDisplayCid(callerAddress, txid), cidDisplay), StringEntry(keyArtType(callerAddress, txid), type), StringEntry(keyArtTags(callerAddress, txid), tags), StringEntry("last_invoke_id", updateId)]
386- }
387- }
388- }
389-
390-
391-
392-@Callable(i)
393-func deleteArtwork (artId,address) = {
394- let callerAddress = toString(addressFromPublicKey(i.callerPublicKey))
395- let id = toBase58String(i.transactionId)
396- let addressToUse = if (if ((callerAddress == admin))
397- then true
398- else (callerAddress == admin2))
399- then address
400- else callerAddress
401- let entryExist = match getString(this, keyArtName(addressToUse, artId)) {
402- case s: String =>
403- s
404- case _ =>
405- throw("No artwork matching this request or you are not allowed")
406- }
407- let artworkMinted = match getInteger(this, keyArtIssued(addressToUse, artId)) {
408- case b: Int =>
409- if ((b == 0))
410- then false
411- else true
412- case _ =>
413- false
414- }
415- let sha256Hash = match getString(this, keyArtHashByTxidAddr(addressToUse, artId)) {
416- case s: String =>
417- s
418- case _ =>
419- throw("No artwork hash matching this request")
420- }
421- let signID = match getString(this, keyArtSignID(addressToUse, artId)) {
422- case s: String =>
423- s
424- case _ =>
425- throw("No SIGN ID matching this request")
426- }
427- let dataToDelete = [DeleteEntry(keyArtDate(addressToUse, artId)), DeleteEntry(keyArtName(addressToUse, artId)), DeleteEntry(keyArtDesc(addressToUse, artId)), DeleteEntry(keyArtDisplayCid(addressToUse, artId)), DeleteEntry(keyArtExportCid(addressToUse, artId)), DeleteEntry(keyArtExportHash(addressToUse, artId)), DeleteEntry(keyArtLicenceHash(addressToUse, artId)), DeleteEntry(keyArtLicenceCid(addressToUse, artId)), DeleteEntry(keyArtType(addressToUse, artId)), DeleteEntry(keyArtTags(addressToUse, artId)), DeleteEntry(keyArtMaxMint(addressToUse, artId)), DeleteEntry(keyArtSignID(addressToUse, artId)), DeleteEntry(keyArtIssued(addressToUse, artId)), DeleteEntry(keyArtOnSale(addressToUse, artId)), StringEntry("last_invoke_id", id), DeleteEntry(keyArtOwnerByHash(sha256Hash)), DeleteEntry(keyArtArtidBySignid(addressToUse, signID)), DeleteEntry(keyArtTxidByHashOwner(sha256Hash, addressToUse))]
428- if (if ((callerAddress == admin))
429- then true
430- else (callerAddress == admin2))
431- then dataToDelete
432- else if (!(artworkMinted))
433- then dataToDelete
434- else throw("This artwork already have minted NFT, you cannot delete it")
435- }
436-
437-
438-
439-@Callable(invoke)
440-func sellArtwork (hash,price) = {
441- let id = toBase58String(invoke.transactionId)
442- let callerAddress = toBase58String(invoke.caller.bytes)
443- let entryDate = lastBlock.timestamp
444- let entryID = getStringByKey(((hash + "_") + callerAddress))
445- if (!(isDefined(entryID)))
446- then throw("This artwork doesn't exit or you are not the owner")
447- else {
448- let userIsRegistered = getStringByKey(("user_status_" + callerAddress))
449- if ((userIsRegistered == ""))
450- then throw("Please register this account first")
451- else {
452- let amountSold = getIntegerByKey(((("art_issued_" + entryID) + "_") + callerAddress))
453- let maxCanSell = getIntegerByKey(((("art_maxmint_" + entryID) + "_") + callerAddress))
454- if ((amountSold == maxCanSell))
455- then throw("You reached the max edition allowed to sell for this edition.")
456- else if ((userIsRegistered == userSuspended))
457- then throw("Your account is suspended")
458- else if (!(isDefined(entryID)))
459- then throw("This artwork desn't exist")
460- else if ((size(hash) != 64))
461- then throw("This hash is incorrect.")
462- else {
463- let sellStatus = if ((price > 0))
464- then true
465- else false
466-[BooleanEntry(((("art_onsale_" + entryID) + "_") + callerAddress), sellStatus), IntegerEntry(((("art_price_" + entryID) + "_") + callerAddress), price), StringEntry("last_invoke_id", id)]
467- }
468- }
469- }
470- }
471-
472-
473-
474-@Callable(invoke)
475-func buyArtwork (hash,issuer) = {
476- let id = toBase58String(invoke.transactionId)
477- let callerAddress = toBase58String(invoke.caller.bytes)
478- let totalNFT = getIntegerByKey("total_nft_issued")
479- let entryID = getStringByKey(((hash + "_") + issuer))
480- if ((entryID == ""))
481- then throw("This artwork doesn't exit or you are not the owner")
482- else {
483- let userIsRegistered = getStringByKey(("user_status_" + callerAddress))
484- if (!(isDefined(userIsRegistered)))
485- then throw("Please register this account first")
486- else {
487- let alreadySoldList = getStringByKey(((("art_sold_" + entryID) + "_") + issuer))
488- let amountSold = getIntegerByKey(((("art_issued_" + entryID) + "_") + issuer))
489- let artworkPrice = getIntegerByKey(((("art_price_" + entryID) + "_") + issuer))
490- if ((artworkPrice == 0))
491- then throw("This artwork is not for sell")
492- else {
493- let maxCanSell = getIntegerByKey(((("art_maxmint_" + entryID) + "_") + issuer))
494- let payment = value(invoke.payments[0])
495- let amount = value(payment.amount)
496- let assetId = if (isDefined(payment.assetId))
497- then throw("Only Waves token accepted at the moment")
498- else unit
499- if ((amountSold == maxCanSell))
500- then throw("Cannot buy this artwork anymore")
501- else if ((artworkPrice != amount))
502- then throw("Payment don't match seller price")
503- else {
504- let newAmountSold = (amountSold + 1)
505- let entryDate = lastBlock.timestamp
506- let issueMeta = (((((((((((((("{\"version\": 1,\"artID\": \"" + entryID) + "\",\"maxIssuable\": \"") + toString(maxCanSell)) + "\",\"signID\": \"SA_") + toString((totalNFT + 1))) + "\", \"creator\": \"") + issuer) + "\", \"issue\": \"") + toString(newAmountSold)) + "/") + toString(maxCanSell)) + "\", \"hash\": ") + hash) + "}")
507- let issueNFT = Issue(("SA_" + toString((totalNFT + 1))), issueMeta, 1, 0, false)
508- let idNFT = calculateAssetId(issueNFT)
509- let sellStatus = if ((newAmountSold == maxCanSell))
510- then false
511- else true
512-[IntegerEntry(((("art_issued_" + entryID) + "_") + issuer), newAmountSold), StringEntry(((((((("art_sold_" + toString(newAmountSold)) + "_of_") + toString(maxCanSell)) + "_") + entryID) + "_") + issuer), ((((((callerAddress + "_") + toString(entryDate)) + "_") + id) + "_") + toString(artworkPrice))), IntegerEntry("total_nft_issued", (totalNFT + 1)), StringEntry("last_invoke_id", id), issueNFT, BooleanEntry(((("art_onsale_" + entryID) + "_") + callerAddress), sellStatus), ScriptTransfer(Address(fromBase58String(issuer)), amount, assetId), ScriptTransfer(invoke.caller, 1, idNFT)]
513- }
514- }
515- }
516- }
517- }
518-
519-
520-
521-@Callable(i)
522-func deleteUser (address) = {
523- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
524- let id = toBase58String(i.transactionId)
525- if (if ((callerAddr == admin))
526- then true
527- else (callerAddr == admin2))
528- then [DeleteEntry(keyUserDate(address)), DeleteEntry(keyUserAddr(address)), DeleteEntry(keyUserName(address)), DeleteEntry(keyUserDesc(address)), DeleteEntry(keyUserSocial(address)), DeleteEntry(keyUserThumb(address)), StringEntry(keyUserStatus(address), userRemoved), StringEntry("last_invoke_id", id)]
529- else throw("You are not allowed to do that")
530705 }
531706
532707
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 4 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let storageVerifier = value(addressFromString("3N2s5RtaHPBenCsx2ECcoFRbYHx3noZhXW1"))
4+let oracleFee = value(addressFromString("3N2s5RtaHPBenCsx2ECcoFRbYHx3noZhXW1"))
55
6-let signVerifier = value(addressFromString("3NC28hSivrmsTUXaYD1x6L362J4ZpUnoTdB"))
6+let signDapp = value(addressFromString("3NC28hSivrmsTUXaYD1x6L362J4ZpUnoTdB"))
77
88 let feeReceiver = "3N1E6tXddRoVaRfQ9dQ3vg5LaW2fsd8HKub"
99
1010 let signAssetId = base58'Gf9t8FA4H3ssoZPCwrg3KwUFCci8zuUFP9ssRsUY3s6a'
1111
12-let usdnID = "3KFXBGGLCjA5Z2DuW4Dq9fDDrHjJJP1ZEkaoajSzuKsC"
12+let usdnAssetId = base58'25FEqEjRkqK6yCkiT7Lz6SAYz7gUFCtxfCChnrVFD5AT'
1313
14-let admin = "3MsG6jPNCrVJUtYB7XJBxS7utWsXAf4n9Vp"
14+let wavesAssetId = base58''
1515
16-let admin2 = "3Mzm4VLwsN9uZwbTMzPj3XuxV6kEfAR8UDN"
16+let signCut = 8
17+
18+let usdnCut = 10
19+
20+let wavesCut = 10
21+
22+let chris = "3MsG6jPNCrVJUtYB7XJBxS7utWsXAf4n9Vp"
23+
24+let joep = "3Mzm4VLwsN9uZwbTMzPj3XuxV6kEfAR8UDN"
1725
1826 let WHITELISTEDONLY = true
27+
28+let dappRunning = true
29+
30+let maintenanceMSG = "SIGN Art is under maintenance"
1931
2032 let userAllowed = "ALLOWED"
2133
2234 let userRegistered = "REGISTERED"
2335
2436 let userVerified = "VERIFIED"
2537
2638 let userSuspended = "SUSPENDED"
2739
2840 let userRemoved = "REMOVED"
2941
42+let userChangeRequired = "CHANGE_REQUIRED"
43+
3044 let userUnregistered = "UNREGISTERED"
3145
32-let onSale = "ON_SALE"
33-
34-let sold = "SOLD"
35-
36-let canceled = "CANCELED"
46+let userReset = "RESET"
3747
3848 func getStringByKey (key) = match getString(this, key) {
3949 case a: String =>
4050 a
4151 case _ =>
4252 ""
53+}
54+
55+
56+func getIntegerByKeyFromOracle (key) = match getInteger(oracleFee, key) {
57+ case a: Int =>
58+ a
59+ case _ =>
60+ throw("Integer undefine or 0 in oracle")
4361 }
4462
4563
4664 func getIntegerByKey (key) = match getInteger(this, key) {
4765 case i: Int =>
4866 i
4967 case _ =>
5068 0
5169 }
5270
5371
54-func checkSignCertificate (signID,Owner,sha256Hash) = match getString(signVerifier, ((("data_fc_" + signID) + "_") + Owner)) {
72+func getBooleanByKey (key) = match getBoolean(this, key) {
73+ case i: Boolean =>
74+ i
75+ case _ =>
76+ false
77+}
78+
79+
80+func checkSignCertificate (signID,Owner,sha256Hash) = match getString(signDapp, ((("data_fc_" + signID) + "_") + Owner)) {
5581 case a: String =>
5682 if (contains(a, sha256Hash))
5783 then true
5884 else false
5985 case _ =>
6086 false
6187 }
6288
6389
64-func validateNFTs (accumulator,id) = {
65- let assetDetails = value(assetInfo(fromBase58String(id)))
66- if (if (if ((assetDetails.quantity != 1))
67- then true
68- else (assetDetails.decimals != 0))
69- then true
70- else (assetDetails.reissuable != false))
71- then (accumulator + 0)
72- else (accumulator + 1)
73- }
90+func validateCID (cid) = if (if ((75 > size(cid)))
91+ then (60 > size(split(cid, "/")[0]))
92+ else false)
93+ then (16 > size(split(cid, "/")[1]))
94+ else false
7495
7596
76-func verifyStatus (addr) = match getString(this, ("user_status_" + addr)) {
77- case b: String =>
78- b
79- case _ =>
80- throw("Something went wrong.")
81-}
97+func validateHash (hash) = (65 > size(hash))
8298
8399
84-func keyUserAddr (callerAddr) = ("user_" + callerAddr)
100+func keyUserAddr (caller) = ("user_" + caller)
85101
86102
87-func keyUserName (callerAddr) = ("user_name_" + callerAddr)
103+func keyUserName (caller) = ("user_name_" + caller)
88104
89105
90-func keyUserDesc (callerAddr) = ("user_desc_" + callerAddr)
106+func keyUserDesc (caller) = ("user_desc_" + caller)
91107
92108
93-func keyUserSocial (callerAddr) = ("user_social_" + callerAddr)
109+func keyUserSocial (caller) = ("user_social_" + caller)
94110
95111
96-func keyUserThumb (callerAddr) = ("user_thumb_" + callerAddr)
112+func keyUserThumb (caller) = ("user_thumb_" + caller)
97113
98114
99-func keyUserStatus (callerAddr) = ("user_status_" + callerAddr)
115+func keyUserStatus (caller) = ("user_status_" + caller)
100116
101117
102-func keyUserDate (callerAddr) = ("user_date_" + callerAddr)
118+func keyUserDate (caller) = ("user_date_" + caller)
103119
104120
105-func keyArtDate (callerAddr,artId) = ((("art_date_" + artId) + "_") + callerAddr)
121+func keyArtDate (caller,artId) = ((("art_date_" + artId) + "_") + caller)
106122
107123
108-func keyArtName (callerAddr,artId) = ((("art_name_" + artId) + "_") + callerAddr)
124+func keyArtName (caller,artId) = ((("art_name_" + artId) + "_") + caller)
109125
110126
111-func keyArtDesc (callerAddr,artId) = ((("art_desc_" + artId) + "_") + callerAddr)
127+func keyArtDesc (caller,artId) = ((("art_desc_" + artId) + "_") + caller)
112128
113129
114-func keyArtDisplayCid (callerAddr,artId) = ((("art_display_cid_" + artId) + "_") + callerAddr)
130+func keyArtDisplayCid (caller,artId) = ((("art_display_cid_" + artId) + "_") + caller)
115131
116132
117-func keyArtExportHash (callerAddr,artId) = ((("art_export_hash_" + artId) + "_") + callerAddr)
133+func keyArtExportHash (caller,artId) = ((("art_export_hash_" + artId) + "_") + caller)
118134
119135
120-func keyArtExportCid (callerAddr,artId) = ((("art_export_cid_" + artId) + "_") + callerAddr)
136+func keyArtExportCid (caller,artId) = ((("art_export_cid_" + artId) + "_") + caller)
121137
122138
123-func keyArtMaxMint (callerAddr,artId) = ((("art_maxmint_" + artId) + "_") + callerAddr)
139+func keyArtMaxMint (caller,artId) = ((("art_maxmint_" + artId) + "_") + caller)
124140
125141
126-func keyArtSignID (callerAddr,artId) = ((("art_signid_" + artId) + "_") + callerAddr)
142+func keyArtSignID (caller,artId) = ((("art_signid_" + artId) + "_") + caller)
127143
128144
129-func keyArtIssued (callerAddr,artId) = ((("art_issued_" + artId) + "_") + callerAddr)
145+func keyArtIssued (caller,artId) = ((("art_issued_" + artId) + "_") + caller)
130146
131147
132-func keyArtOnSale (callerAddr,artId) = ((("art_onsale_" + artId) + "_") + callerAddr)
148+func keyArtOnSale (caller,artId) = ((("art_onsale_" + artId) + "_") + caller)
133149
134150
135-func keyArtLicenceHash (callerAddr,artId) = ((("art_licence_hash_" + artId) + "_") + callerAddr)
151+func keyArtLicenceHash (caller,artId) = ((("art_licence_hash_" + artId) + "_") + caller)
136152
137153
138-func keyArtLicenceCid (callerAddr,artId) = ((("art_licence_cid_" + artId) + "_") + callerAddr)
154+func keyArtLicenceCid (caller,artId) = ((("art_licence_cid_" + artId) + "_") + caller)
139155
140156
141-func keyArtTags (callerAddr,artId) = ((("art_tags_" + artId) + "_") + callerAddr)
157+func keyArtTags (caller,artId) = ((("art_tags_" + artId) + "_") + caller)
142158
143159
144-func keyArtType (callerAddr,artId) = ((("art_type_" + artId) + "_") + callerAddr)
160+func keyArtType (caller,artId) = ((("art_type_" + artId) + "_") + caller)
145161
146162
147-func keyArtHashByTxidAddr (callerAddr,txid) = ((("get_hashbytxidaddr_" + txid) + "_") + callerAddr)
163+func keyArtPrice (caller,artId) = ((("art_price_" + artId) + "_") + caller)
164+
165+
166+func keyArtAssetIdAccepted (caller,artId) = ((("art_assetAccepted_" + artId) + "_") + caller)
167+
168+
169+func keyArtFlag (caller,artId) = ((("art_flag_" + artId) + "_") + caller)
170+
171+
172+func keyArtHashByTxidAddr (caller,txid) = ((("get_hashbytxidaddr_" + txid) + "_") + caller)
148173
149174
150175 func keyArtOwnerByHash (sha256Hash) = ("get_owner_by_hash_" + sha256Hash)
151176
152177
153-func keyArtArtidBySignid (callerAddr,signId) = ((("get_artidbysignid_" + signId) + "_") + callerAddr)
178+func keyArtArtidBySignid (caller,signId) = ((("get_artidbysignid_" + signId) + "_") + caller)
154179
155180
156-func keyArtTxidByHashOwner (sha256Hash,callerAddr) = ("get_txid_by_hash_owner_" + toBase58String(sha256_16Kb(toBytes((sha256Hash + callerAddr)))))
181+func keyArtTxidByHashOwner (sha256Hash,caller) = ("get_txid_by_hash_owner_" + toBase58String(sha256_16Kb(toBytes((sha256Hash + caller)))))
182+
183+
184+func validateAllCID (cidDisplay,cidExport,cidLicence) = if (if ((cidDisplay != ""))
185+ then !(validateCID(cidDisplay))
186+ else false)
187+ then throw("Wrong Display CID")
188+ else if (if ((cidExport != ""))
189+ then !(validateCID(cidExport))
190+ else false)
191+ then throw("Wrong Export CID")
192+ else if (if ((cidLicence != ""))
193+ then !(validateCID(cidLicence))
194+ else false)
195+ then throw("Wrong Licence CID")
196+ else true
197+
198+
199+func validateAllHash (sha256Export,sha256Licence) = if (if ((sha256Export != ""))
200+ then !(validateHash(sha256Export))
201+ else false)
202+ then throw("Export Hash 64 char. max")
203+ else if (if ((sha256Licence != ""))
204+ then !(validateHash(sha256Licence))
205+ else false)
206+ then throw("Licence Hash 64 char. max")
207+ else true
208+
209+
210+func validateString (str,max) = if ((size(str) == 0))
211+ then throw("Field cannot be is empty")
212+ else if ((size(str) > max))
213+ then throw((str + " is too long"))
214+ else true
157215
158216
159217 @Callable(i)
160-func registerUser (name,description,thumb,social) = {
161- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
162- let userCanRegister = getStringByKey(keyUserStatus(callerAddr))
163- let id = toBase58String(i.transactionId)
164- let timestamp = lastBlock.timestamp
165- if (if ((userCanRegister == userSuspended))
166- then true
167- else (userCanRegister == userRemoved))
168- then throw("You are now allowed to register, your account have been suspended/ removed.")
169- else if ((userCanRegister == userRegistered))
170- then throw("You are already registered, please use update method instead.")
171- else if (if ((userCanRegister == ""))
172- then WHITELISTEDONLY
173- else false)
174- then throw("You are now allowed to register yet, please contact us first to get approved.")
218+func registerUser (name,description,thumb,social) = if (!(dappRunning))
219+ then throw(maintenanceMSG)
220+ else {
221+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
222+ let canRegister = getStringByKey(keyUserStatus(caller))
223+ let id = toBase58String(i.transactionId)
224+ let timestamp = lastBlock.timestamp
225+ if (if ((canRegister == userSuspended))
226+ then true
227+ else (canRegister == userRemoved))
228+ then throw("Account suspended/ removed.")
229+ else if ((canRegister == userRegistered))
230+ then throw("Already registered")
231+ else if (if ((canRegister == ""))
232+ then WHITELISTEDONLY
233+ else false)
234+ then throw("Can't register, get approved first.")
235+ else if (if ((name == ""))
236+ then true
237+ else (description == ""))
238+ then throw("Name and description cannot be empty")
239+ else if ((size(description) > 600))
240+ then throw("600 Char. max description")
241+ else if ((size(name) > 45))
242+ then throw("45 Char. max name")
243+ else [IntegerEntry(keyUserDate(caller), timestamp), StringEntry(keyUserAddr(caller), ((id + "_") + toString(timestamp))), StringEntry(keyUserName(caller), name), StringEntry(keyUserDesc(caller), description), StringEntry(keyUserSocial(caller), social), StringEntry(keyUserThumb(caller), thumb), StringEntry(keyUserStatus(caller), userRegistered), StringEntry("last_invoke_id", id)]
244+ }
245+
246+
247+
248+@Callable(i)
249+func updateUser (name,description,thumb,social) = if (!(dappRunning))
250+ then throw(maintenanceMSG)
251+ else {
252+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
253+ let id = toBase58String(i.transactionId)
254+ let canUpdate = getStringByKey(keyUserStatus(caller))
255+ if (if ((canUpdate == userSuspended))
256+ then true
257+ else (canUpdate == userRemoved))
258+ then throw("Account suspended/ removed.")
259+ else if (if ((canUpdate == ""))
260+ then true
261+ else (canUpdate == userAllowed))
262+ then throw("Register first")
175263 else if (if ((name == ""))
176264 then true
177265 else (description == ""))
178- then throw("Name and description cannot be empty")
266+ then throw("Name & description cannot be empty")
179267 else if ((size(description) > 600))
180- then throw("600 Characters maximum for the description")
181- else [IntegerEntry(keyUserDate(callerAddr), timestamp), StringEntry(keyUserAddr(callerAddr), ((id + "_") + toString(lastBlock.timestamp))), StringEntry(keyUserName(callerAddr), name), StringEntry(keyUserDesc(callerAddr), description), StringEntry(keyUserSocial(callerAddr), social), StringEntry(keyUserThumb(callerAddr), thumb), StringEntry(keyUserStatus(callerAddr), userRegistered), StringEntry("last_invoke_id", id)]
268+ then throw("600 Char. max for description")
269+ else if ((size(name) > 45))
270+ then throw("45 Char. max name")
271+ else [StringEntry(keyUserName(caller), name), StringEntry(keyUserDesc(caller), description), StringEntry(keyUserSocial(caller), social), StringEntry(keyUserThumb(caller), thumb), StringEntry("last_invoke_id", id)]
272+ }
273+
274+
275+
276+@Callable(i)
277+func changeUserStatus (address,status) = if (!(dappRunning))
278+ then throw(maintenanceMSG)
279+ else {
280+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
281+ let id = toBase58String(i.transactionId)
282+ let currentStatus = getStringByKey(keyUserStatus(address))
283+ let statusToSet = if ((status == userVerified))
284+ then userVerified
285+ else if ((status == userRegistered))
286+ then userRegistered
287+ else if ((status == userSuspended))
288+ then userSuspended
289+ else if ((status == userRemoved))
290+ then userRemoved
291+ else if ((status == userAllowed))
292+ then userAllowed
293+ else if ((status == userChangeRequired))
294+ then userChangeRequired
295+ else if (if ((status == userReset))
296+ then (currentStatus == userAllowed)
297+ else false)
298+ then ""
299+ else throw("Unknown status")
300+ if (if ((currentStatus == userAllowed))
301+ then (status == userAllowed)
302+ else false)
303+ then throw("User already allowed")
304+ else if (if ((currentStatus == userRegistered))
305+ then (status == userAllowed)
306+ else false)
307+ then throw("User already allowed & registered")
308+ else if (if ((currentStatus == userVerified))
309+ then (status == userAllowed)
310+ else false)
311+ then throw("User already allowed & verified")
312+ else if (containsElement([chris, joep], caller))
313+ then [StringEntry(keyUserStatus(address), statusToSet), StringEntry("last_invoke_id", id)]
314+ else throw(((("Not allowed to change user status " + caller) + " / ") + chris))
315+ }
316+
317+
318+
319+@Callable(invoke)
320+func addArtwork (sha256Hash,signID,name,description,tags,type,maxmint,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence) = if (!(dappRunning))
321+ then throw(maintenanceMSG)
322+ else {
323+ let artId = toBase58String(invoke.transactionId)
324+ let caller = toBase58String(invoke.caller.bytes)
325+ if (!(validateAllCID(cidDisplay, cidExport, cidLicence)))
326+ then throw("Problem with CID")
327+ else if (!(validateHash(sha256Hash)))
328+ then throw("Hash should be 64 characters maximum")
329+ else if (!(validateAllHash(sha256Export, sha256Licence)))
330+ then throw("Problem with Hashes")
331+ else if ((size(invoke.payments) == 0))
332+ then throw("No payment attached")
333+ else {
334+ let payment = value(invoke.payments[0])
335+ let amount = value(payment.amount)
336+ let assetId = if (if (isDefined(payment.assetId))
337+ then (payment.assetId == signAssetId)
338+ else false)
339+ then payment.assetId
340+ else throw("Only SIGN token accepted at the moment")
341+ let currentCertificationPrice = getIntegerByKeyFromOracle(("certification_fee_" + toBase58String(signAssetId)))
342+ if ((amount != currentCertificationPrice))
343+ then throw(("Payment amount should be " + toString(currentCertificationPrice)))
344+ else {
345+ let entryExist = getStringByKey(keyArtTxidByHashOwner(sha256Hash, caller))
346+ if ((entryExist != ""))
347+ then throw("You already added it")
348+ else {
349+ let hashExist = getStringByKey(keyArtOwnerByHash(sha256Hash))
350+ if ((hashExist != ""))
351+ then throw("Hash already registered")
352+ else {
353+ let isSignCertified = checkSignCertificate(signID, caller, sha256Hash)
354+ if (!(isSignCertified))
355+ then throw("Sign Certificate not found for this address.")
356+ else if ((size(cidDisplay) == 0))
357+ then throw("Display CID cannot be empty")
358+ else if (!(validateString(name, 100)))
359+ then throw("100 Char. max name")
360+ else if (!(validateString(description, 1000)))
361+ then throw("1000 Char. max description")
362+ else if ((size(split(tags, ",")) > 5))
363+ then throw("5 tags max.")
364+ else {
365+ let userIsRegistered = match getString(this, ("user_status_" + caller)) {
366+ case s: String =>
367+ s
368+ case _ =>
369+ userUnregistered
370+ }
371+ let timestamp = lastBlock.timestamp
372+ if (if (isDefined(userIsRegistered))
373+ then (userIsRegistered == userUnregistered)
374+ else false)
375+ then throw("Register this account first with \"User infos\" tab")
376+ else if ((userIsRegistered == userSuspended))
377+ then throw("Account suspended")
378+ else if ((userIsRegistered == userRemoved))
379+ then throw("Account removed")
380+ else if ((maxmint > 10))
381+ then throw("10 editions max")
382+ else if ((size(sha256Hash) != 64))
383+ then throw("Hash 64 char. max")
384+ else [StringEntry(keyArtOwnerByHash(sha256Hash), caller), StringEntry(keyArtTxidByHashOwner(sha256Hash, caller), artId), IntegerEntry(keyArtDate(caller, artId), timestamp), StringEntry(keyArtName(caller, artId), name), StringEntry(keyArtDesc(caller, artId), description), StringEntry(keyArtDisplayCid(caller, artId), cidDisplay), StringEntry(keyArtExportCid(caller, artId), cidExport), StringEntry(keyArtExportHash(caller, artId), sha256Export), StringEntry(keyArtLicenceHash(caller, artId), sha256Licence), StringEntry(keyArtLicenceCid(caller, artId), cidLicence), StringEntry(keyArtType(caller, artId), type), StringEntry(keyArtTags(caller, artId), tags), IntegerEntry(keyArtMaxMint(caller, artId), maxmint), StringEntry(keyArtSignID(caller, artId), signID), IntegerEntry(keyArtIssued(caller, artId), 0), BooleanEntry(keyArtOnSale(caller, artId), false), StringEntry(keyArtArtidBySignid(caller, signID), artId), StringEntry("last_invoke_id", artId), StringEntry(keyArtHashByTxidAddr(caller, artId), sha256Hash), ScriptTransfer(Address(fromBase58String(feeReceiver)), amount, assetId)]
385+ }
386+ }
387+ }
388+ }
389+ }
390+ }
391+
392+
393+
394+@Callable(invoke)
395+func updateArtwork (txid,name,description,tags,type,maxmint,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence) = if (!(dappRunning))
396+ then throw(maintenanceMSG)
397+ else {
398+ let updateId = toBase58String(invoke.transactionId)
399+ let caller = toBase58String(invoke.caller.bytes)
400+ if (!(validateAllCID(cidDisplay, cidExport, cidLicence)))
401+ then throw("Problem with CID")
402+ else if (!(validateAllHash(sha256Export, sha256Licence)))
403+ then throw("Problem with Hashes")
404+ else {
405+ let entryExist = getStringByKey(keyArtName(caller, txid))
406+ if ((entryExist == ""))
407+ then throw("Entry not found")
408+ else if (!(validateString(name, 100)))
409+ then throw("100 Char. max name")
410+ else if (!(validateString(description, 1000)))
411+ then throw("1000 Char. max description")
412+ else {
413+ let flag = getStringByKey(keyArtFlag(caller, txid))
414+ if ((flag == "ILLEGAL"))
415+ then throw("Cannot update")
416+ else {
417+ let artworkMinted = match getInteger(this, keyArtIssued(caller, txid)) {
418+ case b: Int =>
419+ if ((b == 0))
420+ then false
421+ else true
422+ case _ =>
423+ false
424+ }
425+ if ((size(split(tags, ",")) > 5))
426+ then throw("5 tags max.")
427+ else {
428+ let userIsRegistered = match getString(this, ("user_status_" + caller)) {
429+ case s: String =>
430+ s
431+ case _ =>
432+ userUnregistered
433+ }
434+ if (if (isDefined(userIsRegistered))
435+ then (userIsRegistered == userUnregistered)
436+ else false)
437+ then throw("Register first with \"User infos\"")
438+ else if ((userIsRegistered == userSuspended))
439+ then throw("Account suspended")
440+ else if ((userIsRegistered == userRemoved))
441+ then throw("Account removed")
442+ else if ((maxmint > 10))
443+ then throw("10 editions max per artwork")
444+ else if (!(artworkMinted))
445+ then [StringEntry(keyArtName(caller, txid), name), StringEntry(keyArtDesc(caller, txid), description), StringEntry(keyArtDisplayCid(caller, txid), cidDisplay), StringEntry(keyArtExportCid(caller, txid), cidExport), StringEntry(keyArtExportHash(caller, txid), sha256Export), StringEntry(keyArtLicenceCid(caller, txid), cidLicence), StringEntry(keyArtLicenceHash(caller, txid), sha256Licence), IntegerEntry(keyArtMaxMint(caller, txid), maxmint), StringEntry(keyArtTags(caller, txid), tags), StringEntry(keyArtType(caller, txid), type), StringEntry("last_invoke_id", updateId)]
446+ else throw("Already minted")
447+ }
448+ }
449+ }
450+ }
451+ }
452+
453+
454+
455+@Callable(i)
456+func flagArtwork (artId,addr,flag) = {
457+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
458+ let id = toBase58String(i.transactionId)
459+ if (containsElement([chris, joep], caller))
460+ then if ((flag == "CONSENT"))
461+ then [StringEntry(keyArtFlag(addr, artId), flag), StringEntry("last_invoke_id", id)]
462+ else if ((flag == ""))
463+ then [StringEntry(keyArtFlag(addr, artId), flag), StringEntry("last_invoke_id", id)]
464+ else if ((flag == "ILLEGAL"))
465+ then [StringEntry(keyArtFlag(addr, artId), flag), StringEntry(keyArtName(addr, artId), "ILLEGAL CONTENT"), StringEntry(keyArtDesc(addr, artId), "ILLEGAL CONTENT"), StringEntry(keyArtDisplayCid(addr, artId), ""), StringEntry(keyArtExportCid(addr, artId), ""), StringEntry(keyArtLicenceCid(addr, artId), ""), StringEntry("last_invoke_id", id)]
466+ else throw(("Unknow status" + flag))
467+ else throw("no")
468+ }
469+
470+
471+
472+@Callable(i)
473+func deleteArtwork (artId,addr) = {
474+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
475+ let id = toBase58String(i.transactionId)
476+ let addressToUse = if (containsElement([chris, joep], caller))
477+ then addr
478+ else caller
479+ let entryExist = match getString(this, keyArtName(addressToUse, artId)) {
480+ case s: String =>
481+ s
482+ case _ =>
483+ throw("No art matching")
484+ }
485+ let artworkMinted = match getInteger(this, keyArtIssued(addressToUse, artId)) {
486+ case b: Int =>
487+ if ((b != 0))
488+ then true
489+ else false
490+ case _ =>
491+ false
492+ }
493+ let maxMint = getIntegerByKey(keyArtMaxMint(addressToUse, artId))
494+ let sha256Hash = match getString(this, keyArtHashByTxidAddr(addressToUse, artId)) {
495+ case s: String =>
496+ s
497+ case _ =>
498+ throw("No art hash matching")
499+ }
500+ let signID = match getString(this, keyArtSignID(addressToUse, artId)) {
501+ case s: String =>
502+ s
503+ case _ =>
504+ throw("No SIGN ID matching")
505+ }
506+ let dataToDelete = [DeleteEntry(keyArtDate(addressToUse, artId)), DeleteEntry(keyArtName(addressToUse, artId)), DeleteEntry(keyArtDesc(addressToUse, artId)), DeleteEntry(keyArtDisplayCid(addressToUse, artId)), DeleteEntry(keyArtExportCid(addressToUse, artId)), DeleteEntry(keyArtExportHash(addressToUse, artId)), DeleteEntry(keyArtLicenceHash(addressToUse, artId)), DeleteEntry(keyArtLicenceCid(addressToUse, artId)), DeleteEntry(keyArtType(addressToUse, artId)), DeleteEntry(keyArtTags(addressToUse, artId)), DeleteEntry(keyArtMaxMint(addressToUse, artId)), DeleteEntry(keyArtSignID(addressToUse, artId)), DeleteEntry(keyArtIssued(addressToUse, artId)), DeleteEntry(keyArtOnSale(addressToUse, artId)), DeleteEntry(keyArtFlag(addr, artId)), StringEntry("last_invoke_id", id), DeleteEntry(keyArtOwnerByHash(sha256Hash)), DeleteEntry(keyArtArtidBySignid(addressToUse, signID)), DeleteEntry(keyArtTxidByHashOwner(sha256Hash, addressToUse))]
507+ if (!(artworkMinted))
508+ then if (!(dappRunning))
509+ then throw(maintenanceMSG)
510+ else dataToDelete
511+ else throw("Art already minted, cannot delete")
512+ }
513+
514+
515+
516+@Callable(i)
517+func sellArtwork (artId,price,maxMint,assetId) = if (!(dappRunning))
518+ then throw(maintenanceMSG)
519+ else {
520+ let id = toBase58String(i.transactionId)
521+ let caller = toBase58String(i.caller.bytes)
522+ let sellDate = lastBlock.timestamp
523+ let exportCID = getStringByKey(keyArtExportCid(caller, artId))
524+ if ((size(split(exportCID, "/")[0]) != 59))
525+ then throw("You cannot sell art with no export file")
526+ else {
527+ let exportHash = getStringByKey(keyArtExportHash(caller, artId))
528+ if ((size(exportHash) != 64))
529+ then throw("You cannot sell art with no export hash")
530+ else if (if (if ((assetId != toBase58String(signAssetId)))
531+ then (assetId != toBase58String(wavesAssetId))
532+ else false)
533+ then (assetId != toBase58String(usdnAssetId))
534+ else false)
535+ then throw("Only SIGN, USDN or WAVES accepted")
536+ else {
537+ let minSellWaves = getIntegerByKeyFromOracle("waves_min_sell")
538+ let minSellUsdn = 1000000
539+ let minSellSign = (getIntegerByKeyFromOracle(("certification_fee_" + toBase58String(signAssetId))) * 2)
540+ if (if (if (if (if ((assetId == toBase58String(usdnAssetId)))
541+ then (minSellUsdn > price)
542+ else false)
543+ then (price != 0)
544+ else false)
545+ then true
546+ else if (if ((assetId == toBase58String(signAssetId)))
547+ then (minSellSign > price)
548+ else false)
549+ then (price != 0)
550+ else false)
551+ then true
552+ else if (if ((assetId == toBase58String(wavesAssetId)))
553+ then (minSellWaves > price)
554+ else false)
555+ then (price != 0)
556+ else false)
557+ then throw("Wrong minimum sell price")
558+ else {
559+ let artworkName = match getString(this, keyArtName(caller, artId)) {
560+ case s: String =>
561+ s
562+ case _ =>
563+ throw("This art doesn't match")
564+ }
565+ let userIsRegistered = match getString(this, keyUserStatus(caller)) {
566+ case s: String =>
567+ s
568+ case _ =>
569+ throw("Register this account first")
570+ }
571+ let amountSold = getIntegerByKey(keyArtIssued(caller, artId))
572+ let maxCanSell = getIntegerByKey(keyArtMaxMint(caller, artId))
573+ if (if ((amountSold != 0))
574+ then (amountSold == maxCanSell)
575+ else false)
576+ then throw("Max edition reached.")
577+ else if (if ((amountSold > 0))
578+ then (maxCanSell != maxMint)
579+ else false)
580+ then throw("Cannot change maximum issuable anymore")
581+ else if ((userIsRegistered == userSuspended))
582+ then throw("Account suspended")
583+ else if ((userIsRegistered == userRemoved))
584+ then throw("Account deleted")
585+ else {
586+ let sellStatus = if (if ((price > 0))
587+ then (maxMint > 0)
588+ else false)
589+ then true
590+ else false
591+[BooleanEntry(keyArtOnSale(caller, artId), sellStatus), IntegerEntry(keyArtPrice(caller, artId), price), IntegerEntry(keyArtMaxMint(caller, artId), maxMint), StringEntry(keyArtAssetIdAccepted(caller, artId), assetId), StringEntry("last_invoke_id", id)]
592+ }
593+ }
594+ }
595+ }
596+ }
597+
598+
599+
600+@Callable(i)
601+func buyArtwork (artId,issuer) = if (!(dappRunning))
602+ then throw(maintenanceMSG)
603+ else {
604+ let id = toBase58String(i.transactionId)
605+ let caller = toBase58String(i.caller.bytes)
606+ let totalNFT = getIntegerByKey("total_nft_issued")
607+ let signID = getStringByKey(keyArtSignID(issuer, artId))
608+ let artworkName = match getString(this, keyArtName(issuer, artId)) {
609+ case s: String =>
610+ s
611+ case _ =>
612+ throw("Art doesn't exist")
613+ }
614+ let displayCID = getStringByKey(keyArtDisplayCid(issuer, artId))
615+ let exportCID = getStringByKey(keyArtExportCid(issuer, artId))
616+ let exportHash = getStringByKey(keyArtExportHash(issuer, artId))
617+ let licenceCID = getStringByKey(keyArtLicenceCid(issuer, artId))
618+ let licenceHash = getStringByKey(keyArtLicenceHash(issuer, artId))
619+ let description = take(getStringByKey(keyArtDesc(issuer, artId)), 50)
620+ let amountSold = getIntegerByKey(keyArtIssued(issuer, artId))
621+ let artworkPrice = getIntegerByKey(keyArtPrice(issuer, artId))
622+ let isOnSale = getBooleanByKey(keyArtOnSale(issuer, artId))
623+ let priceAssetId = getStringByKey(keyArtAssetIdAccepted(issuer, artId))
624+ let sourceHash = getStringByKey(keyArtHashByTxidAddr(issuer, artId))
625+ if ((artworkPrice == 0))
626+ then throw("Art not for sell")
627+ else if (!(isOnSale))
628+ then throw("Art not for sale")
629+ else {
630+ let maxCanSell = getIntegerByKey(keyArtMaxMint(issuer, artId))
631+ let payment = value(i.payments[0])
632+ let amount = value(payment.amount)
633+ let assetId = if (if (if (isDefined(payment.assetId))
634+ then (size(fromBase58String(priceAssetId)) > 0)
635+ else false)
636+ then (payment.assetId == fromBase58String(priceAssetId))
637+ else false)
638+ then payment.assetId
639+ else unit
640+ let cut = if ((priceAssetId == toBase58String(signAssetId)))
641+ then 8
642+ else 10
643+ let amountForSign = fraction(amount, cut, 100)
644+ let amountForCreator = (amount - amountForSign)
645+ if ((amountSold == maxCanSell))
646+ then throw("Art sold out")
647+ else if ((artworkPrice != amount))
648+ then throw("Payment don't match")
649+ else {
650+ let newAmountSold = (amountSold + 1)
651+ let entryDate = lastBlock.timestamp
652+ let issueMeta = ((((((((((((((((((((((((((("Creator: " + issuer) + ",
653+ ArtID: ") + artId) + ",
654+ SignID: ") + signID) + ",
655+ Artwork name: ") + artworkName) + ",
656+ Artwork description: ") + description) + ",
657+ Issue: ") + toString(newAmountSold)) + "/") + toString(maxCanSell)) + ",
658+ Max issuable: ") + toString(maxCanSell)) + ",
659+ Source hash: ") + sourceHash) + ",
660+ Display cid: ") + displayCID) + ",
661+ Export cid: ") + exportCID) + ",
662+ Export hash: ") + exportHash) + ",
663+ Licence cid: ") + licenceCID) + ",
664+ Licence hash: ") + licenceHash)
665+ let issueNFT = Issue(("SA_" + toString((totalNFT + 1))), issueMeta, 1, 0, false)
666+ let idNFT = calculateAssetId(issueNFT)
667+ let sellStatus = if ((newAmountSold == maxCanSell))
668+ then false
669+ else true
670+[IntegerEntry(keyArtIssued(issuer, artId), newAmountSold), StringEntry(((((((("art_sold_" + toString(newAmountSold)) + "_of_") + toString(maxCanSell)) + "_") + artId) + "_") + issuer), ((((((((((caller + "_") + toString(entryDate)) + "_") + id) + "_") + toString(artworkPrice)) + "_") + priceAssetId) + "_") + toBase58String(idNFT))), IntegerEntry("total_nft_issued", (totalNFT + 1)), BooleanEntry(keyArtOnSale(issuer, artId), sellStatus), StringEntry("last_invoke_id", id), issueNFT, ScriptTransfer(Address(fromBase58String(issuer)), amountForCreator, assetId), ScriptTransfer(Address(fromBase58String(feeReceiver)), amountForSign, assetId), ScriptTransfer(i.caller, 1, idNFT)]
671+ }
672+ }
673+ }
674+
675+
676+
677+@Callable(i)
678+func creditUser (address) = {
679+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
680+ let id = toBase58String(i.transactionId)
681+ if (containsElement([chris, joep], caller))
682+ then [ScriptTransfer(Address(fromBase58String(address)), 150000000000, signAssetId)]
683+ else throw("Not allowed")
684+ }
685+
686+
687+
688+@Callable(i)
689+func deleteUser (address) = {
690+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
691+ let id = toBase58String(i.transactionId)
692+ if (containsElement([chris, joep], caller))
693+ then [DeleteEntry(keyUserDate(address)), DeleteEntry(keyUserAddr(address)), DeleteEntry(keyUserName(address)), DeleteEntry(keyUserDesc(address)), DeleteEntry(keyUserSocial(address)), DeleteEntry(keyUserThumb(address)), StringEntry(keyUserStatus(address), userRemoved), StringEntry("last_invoke_id", id)]
694+ else throw("Not allowed")
182695 }
183696
184697
185698
186699 @Callable(i)
187700 func deleteEntry (entry) = {
188- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
189- if ((callerAddr == admin))
701+ let caller = toString(addressFromPublicKey(i.callerPublicKey))
702+ if ((caller == chris))
190703 then [DeleteEntry(entry)]
191704 else throw("no")
192- }
193-
194-
195-
196-@Callable(i)
197-func updateUser (name,description,thumb,social) = {
198- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
199- let userCanRegister = getStringByKey(keyUserStatus(callerAddr))
200- if (if ((userCanRegister == userSuspended))
201- then true
202- else (userCanRegister == userRemoved))
203- then throw("You are now allowed to register, your account have been suspended/ removed.")
204- else if (if ((userCanRegister == ""))
205- then true
206- else (userCanRegister == userAllowed))
207- then throw("Please register first with registerUser")
208- else {
209- let id = toBase58String(i.transactionId)
210- let timestamp = lastBlock.timestamp
211- if (if ((name == ""))
212- then true
213- else (description == ""))
214- then throw("Name and description cannot be empty")
215- else if ((size(description) > 600))
216- then throw("600 Characters maximum for the description")
217- else [StringEntry(keyUserName(callerAddr), name), StringEntry(keyUserDesc(callerAddr), description), StringEntry(keyUserSocial(callerAddr), social), StringEntry(keyUserThumb(callerAddr), thumb), StringEntry("last_invoke_id", id)]
218- }
219- }
220-
221-
222-
223-@Callable(i)
224-func changeUserStatus (address,status) = {
225- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
226- let id = toBase58String(i.transactionId)
227- let statusToSet = if ((status == userVerified))
228- then userVerified
229- else if ((status == userRegistered))
230- then userRegistered
231- else if ((status == userSuspended))
232- then userSuspended
233- else if ((status == userRemoved))
234- then userRemoved
235- else if ((status == userAllowed))
236- then userAllowed
237- else throw("Unknown status")
238- if (if ((callerAddr == admin))
239- then true
240- else (callerAddr == admin2))
241- then [StringEntry(keyUserStatus(address), statusToSet), StringEntry("last_invoke_id", id)]
242- else throw(((("You are not allowed to change user status " + callerAddr) + " / ") + admin))
243- }
244-
245-
246-
247-@Callable(i)
248-func creditUser (address) = {
249- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
250- let id = toBase58String(i.transactionId)
251- if (if ((callerAddr == admin))
252- then true
253- else (callerAddr == admin2))
254- then [ScriptTransfer(Address(fromBase58String(address)), 150000000000, signAssetId)]
255- else throw("You are not allowed to do that")
256- }
257-
258-
259-
260-@Callable(invoke)
261-func addArtwork (sha256Hash,signID,name,description,tags,type,maxmint,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence) = {
262- let artId = toBase58String(invoke.transactionId)
263- let callerAddress = toBase58String(invoke.caller.bytes)
264- if ((size(invoke.payments) == 0))
265- then throw("No payment attached")
266- else {
267- let payment = value(invoke.payments[0])
268- let amount = value(payment.amount)
269- let assetId = if (if (isDefined(payment.assetId))
270- then (payment.assetId == signAssetId)
271- else false)
272- then payment.assetId
273- else throw("Only SIGN token accepted at the moment")
274- let currentCertificationPrice = match getInteger(storageVerifier, ("certification_fee_" + toBase58String(signAssetId))) {
275- case price: Int =>
276- price
277- case _ =>
278- throw("Price undefined in oracle")
279- }
280- if ((amount != currentCertificationPrice))
281- then throw(("Payment amount should be " + toString(currentCertificationPrice)))
282- else {
283- let entryExist = getStringByKey(keyArtTxidByHashOwner(sha256Hash, callerAddress))
284- if ((entryExist != ""))
285- then throw("You already added this artwork on Sign Art")
286- else {
287- let hashExist = getStringByKey(keyArtOwnerByHash(sha256Hash))
288- if ((hashExist != ""))
289- then throw("This artwork hash is already registered on Sign Art")
290- else {
291- let isSignCertified = checkSignCertificate(signID, callerAddress, sha256Hash)
292- if (!(isSignCertified))
293- then throw("Sign Certificate not found on Sign-web.app smart contract for this address.")
294- else if ((size(cidDisplay) == 0))
295- then throw("Display CID cannot be empty")
296- else if ((size(name) == 0))
297- then throw("Title cannot be empty")
298- else if ((size(name) > 100))
299- then throw("100 Characters maximum for the name")
300- else if ((size(description) > 1000))
301- then throw("1000 Characters maximum for the description")
302- else if ((size(description) == 0))
303- then throw("Description cannot be empty")
304- else {
305- let tagsList = split(tags, ",")
306- if ((size(tagsList) > 5))
307- then throw("Tags should be maximum 5 single word separated by space.")
308- else {
309- let userIsRegistered = match getString(this, ("user_status_" + callerAddress)) {
310- case s: String =>
311- s
312- case _ =>
313- userUnregistered
314- }
315- let timestamp = lastBlock.timestamp
316- if (if (isDefined(userIsRegistered))
317- then (userIsRegistered == userUnregistered)
318- else false)
319- then throw("Please register this account first with \"User infos\" tab")
320- else if ((userIsRegistered == userSuspended))
321- then throw("Your account is suspended")
322- else if ((userIsRegistered == userRemoved))
323- then throw("Your account have been removed")
324- else if ((maxmint > 10))
325- then throw("Maximum 10 editions per artwork")
326- else if ((size(sha256Hash) != 64))
327- then throw("Hash should be sha256 string composed of 64 char.")
328- else [StringEntry(keyArtOwnerByHash(sha256Hash), callerAddress), StringEntry(keyArtTxidByHashOwner(sha256Hash, callerAddress), artId), IntegerEntry(keyArtDate(callerAddress, artId), timestamp), StringEntry(keyArtName(callerAddress, artId), name), StringEntry(keyArtDesc(callerAddress, artId), description), StringEntry(keyArtDisplayCid(callerAddress, artId), cidDisplay), StringEntry(keyArtExportCid(callerAddress, artId), cidExport), StringEntry(keyArtExportHash(callerAddress, artId), sha256Export), StringEntry(keyArtLicenceHash(callerAddress, artId), sha256Licence), StringEntry(keyArtLicenceCid(callerAddress, artId), cidLicence), StringEntry(keyArtType(callerAddress, artId), type), StringEntry(keyArtTags(callerAddress, artId), tags), IntegerEntry(keyArtMaxMint(callerAddress, artId), maxmint), StringEntry(keyArtSignID(callerAddress, artId), signID), IntegerEntry(keyArtIssued(callerAddress, artId), 0), BooleanEntry(keyArtOnSale(callerAddress, artId), false), StringEntry(keyArtArtidBySignid(callerAddress, signID), artId), StringEntry("last_invoke_id", artId), StringEntry(keyArtHashByTxidAddr(callerAddress, artId), sha256Hash), ScriptTransfer(Address(fromBase58String(feeReceiver)), amount, assetId)]
329- }
330- }
331- }
332- }
333- }
334- }
335- }
336-
337-
338-
339-@Callable(invoke)
340-func updateArtwork (txid,name,description,tags,type,maxmint,cidDisplay,sha256Export,cidExport,sha256Licence,cidLicence) = {
341- let updateId = toBase58String(invoke.transactionId)
342- let callerAddress = toBase58String(invoke.caller.bytes)
343- let entryExist = getStringByKey(keyArtName(callerAddress, txid))
344- if ((entryExist == ""))
345- then throw("This entry doesn't exist or you are not the owner")
346- else if ((size(name) == 0))
347- then throw("Title cannot be empty")
348- else if ((size(name) > 100))
349- then throw("100 Characters maximum for the name")
350- else if ((size(description) > 1000))
351- then throw("1000 Characters maximum for the description")
352- else if ((size(description) == 0))
353- then throw("Description cannot be empty")
354- else {
355- let artworkMinted = match getInteger(this, keyArtIssued(callerAddress, txid)) {
356- case b: Int =>
357- if ((b == 0))
358- then false
359- else true
360- case _ =>
361- false
362- }
363- let tagsList = split(tags, ",")
364- if ((size(tagsList) > 5))
365- then throw("Tags should be maximum 5 single word separated by space.")
366- else {
367- let userIsRegistered = match getString(this, ("user_status_" + callerAddress)) {
368- case s: String =>
369- s
370- case _ =>
371- userUnregistered
372- }
373- if (if (isDefined(userIsRegistered))
374- then (userIsRegistered == userUnregistered)
375- else false)
376- then throw("Please register this account first with \"User infos\" tab")
377- else if ((userIsRegistered == userSuspended))
378- then throw("Your account is suspended")
379- else if ((userIsRegistered == userRemoved))
380- then throw("Your account have been removed")
381- else if ((maxmint > 10))
382- then throw("Maximum 10 editions per artwork")
383- else if (!(artworkMinted))
384- then [StringEntry(keyArtName(callerAddress, txid), name), StringEntry(keyArtDesc(callerAddress, txid), description), StringEntry(keyArtDisplayCid(callerAddress, txid), cidDisplay), StringEntry(keyArtExportCid(callerAddress, txid), cidExport), StringEntry(keyArtExportHash(callerAddress, txid), sha256Export), StringEntry(keyArtLicenceCid(callerAddress, txid), cidLicence), StringEntry(keyArtLicenceHash(callerAddress, txid), sha256Licence), IntegerEntry(keyArtMaxMint(callerAddress, txid), maxmint), StringEntry(keyArtTags(callerAddress, txid), tags), StringEntry(keyArtType(callerAddress, txid), type), StringEntry("last_invoke_id", updateId)]
385- else [StringEntry(keyArtName(callerAddress, txid), name), StringEntry(keyArtDesc(callerAddress, txid), description), StringEntry(keyArtDisplayCid(callerAddress, txid), cidDisplay), StringEntry(keyArtType(callerAddress, txid), type), StringEntry(keyArtTags(callerAddress, txid), tags), StringEntry("last_invoke_id", updateId)]
386- }
387- }
388- }
389-
390-
391-
392-@Callable(i)
393-func deleteArtwork (artId,address) = {
394- let callerAddress = toString(addressFromPublicKey(i.callerPublicKey))
395- let id = toBase58String(i.transactionId)
396- let addressToUse = if (if ((callerAddress == admin))
397- then true
398- else (callerAddress == admin2))
399- then address
400- else callerAddress
401- let entryExist = match getString(this, keyArtName(addressToUse, artId)) {
402- case s: String =>
403- s
404- case _ =>
405- throw("No artwork matching this request or you are not allowed")
406- }
407- let artworkMinted = match getInteger(this, keyArtIssued(addressToUse, artId)) {
408- case b: Int =>
409- if ((b == 0))
410- then false
411- else true
412- case _ =>
413- false
414- }
415- let sha256Hash = match getString(this, keyArtHashByTxidAddr(addressToUse, artId)) {
416- case s: String =>
417- s
418- case _ =>
419- throw("No artwork hash matching this request")
420- }
421- let signID = match getString(this, keyArtSignID(addressToUse, artId)) {
422- case s: String =>
423- s
424- case _ =>
425- throw("No SIGN ID matching this request")
426- }
427- let dataToDelete = [DeleteEntry(keyArtDate(addressToUse, artId)), DeleteEntry(keyArtName(addressToUse, artId)), DeleteEntry(keyArtDesc(addressToUse, artId)), DeleteEntry(keyArtDisplayCid(addressToUse, artId)), DeleteEntry(keyArtExportCid(addressToUse, artId)), DeleteEntry(keyArtExportHash(addressToUse, artId)), DeleteEntry(keyArtLicenceHash(addressToUse, artId)), DeleteEntry(keyArtLicenceCid(addressToUse, artId)), DeleteEntry(keyArtType(addressToUse, artId)), DeleteEntry(keyArtTags(addressToUse, artId)), DeleteEntry(keyArtMaxMint(addressToUse, artId)), DeleteEntry(keyArtSignID(addressToUse, artId)), DeleteEntry(keyArtIssued(addressToUse, artId)), DeleteEntry(keyArtOnSale(addressToUse, artId)), StringEntry("last_invoke_id", id), DeleteEntry(keyArtOwnerByHash(sha256Hash)), DeleteEntry(keyArtArtidBySignid(addressToUse, signID)), DeleteEntry(keyArtTxidByHashOwner(sha256Hash, addressToUse))]
428- if (if ((callerAddress == admin))
429- then true
430- else (callerAddress == admin2))
431- then dataToDelete
432- else if (!(artworkMinted))
433- then dataToDelete
434- else throw("This artwork already have minted NFT, you cannot delete it")
435- }
436-
437-
438-
439-@Callable(invoke)
440-func sellArtwork (hash,price) = {
441- let id = toBase58String(invoke.transactionId)
442- let callerAddress = toBase58String(invoke.caller.bytes)
443- let entryDate = lastBlock.timestamp
444- let entryID = getStringByKey(((hash + "_") + callerAddress))
445- if (!(isDefined(entryID)))
446- then throw("This artwork doesn't exit or you are not the owner")
447- else {
448- let userIsRegistered = getStringByKey(("user_status_" + callerAddress))
449- if ((userIsRegistered == ""))
450- then throw("Please register this account first")
451- else {
452- let amountSold = getIntegerByKey(((("art_issued_" + entryID) + "_") + callerAddress))
453- let maxCanSell = getIntegerByKey(((("art_maxmint_" + entryID) + "_") + callerAddress))
454- if ((amountSold == maxCanSell))
455- then throw("You reached the max edition allowed to sell for this edition.")
456- else if ((userIsRegistered == userSuspended))
457- then throw("Your account is suspended")
458- else if (!(isDefined(entryID)))
459- then throw("This artwork desn't exist")
460- else if ((size(hash) != 64))
461- then throw("This hash is incorrect.")
462- else {
463- let sellStatus = if ((price > 0))
464- then true
465- else false
466-[BooleanEntry(((("art_onsale_" + entryID) + "_") + callerAddress), sellStatus), IntegerEntry(((("art_price_" + entryID) + "_") + callerAddress), price), StringEntry("last_invoke_id", id)]
467- }
468- }
469- }
470- }
471-
472-
473-
474-@Callable(invoke)
475-func buyArtwork (hash,issuer) = {
476- let id = toBase58String(invoke.transactionId)
477- let callerAddress = toBase58String(invoke.caller.bytes)
478- let totalNFT = getIntegerByKey("total_nft_issued")
479- let entryID = getStringByKey(((hash + "_") + issuer))
480- if ((entryID == ""))
481- then throw("This artwork doesn't exit or you are not the owner")
482- else {
483- let userIsRegistered = getStringByKey(("user_status_" + callerAddress))
484- if (!(isDefined(userIsRegistered)))
485- then throw("Please register this account first")
486- else {
487- let alreadySoldList = getStringByKey(((("art_sold_" + entryID) + "_") + issuer))
488- let amountSold = getIntegerByKey(((("art_issued_" + entryID) + "_") + issuer))
489- let artworkPrice = getIntegerByKey(((("art_price_" + entryID) + "_") + issuer))
490- if ((artworkPrice == 0))
491- then throw("This artwork is not for sell")
492- else {
493- let maxCanSell = getIntegerByKey(((("art_maxmint_" + entryID) + "_") + issuer))
494- let payment = value(invoke.payments[0])
495- let amount = value(payment.amount)
496- let assetId = if (isDefined(payment.assetId))
497- then throw("Only Waves token accepted at the moment")
498- else unit
499- if ((amountSold == maxCanSell))
500- then throw("Cannot buy this artwork anymore")
501- else if ((artworkPrice != amount))
502- then throw("Payment don't match seller price")
503- else {
504- let newAmountSold = (amountSold + 1)
505- let entryDate = lastBlock.timestamp
506- let issueMeta = (((((((((((((("{\"version\": 1,\"artID\": \"" + entryID) + "\",\"maxIssuable\": \"") + toString(maxCanSell)) + "\",\"signID\": \"SA_") + toString((totalNFT + 1))) + "\", \"creator\": \"") + issuer) + "\", \"issue\": \"") + toString(newAmountSold)) + "/") + toString(maxCanSell)) + "\", \"hash\": ") + hash) + "}")
507- let issueNFT = Issue(("SA_" + toString((totalNFT + 1))), issueMeta, 1, 0, false)
508- let idNFT = calculateAssetId(issueNFT)
509- let sellStatus = if ((newAmountSold == maxCanSell))
510- then false
511- else true
512-[IntegerEntry(((("art_issued_" + entryID) + "_") + issuer), newAmountSold), StringEntry(((((((("art_sold_" + toString(newAmountSold)) + "_of_") + toString(maxCanSell)) + "_") + entryID) + "_") + issuer), ((((((callerAddress + "_") + toString(entryDate)) + "_") + id) + "_") + toString(artworkPrice))), IntegerEntry("total_nft_issued", (totalNFT + 1)), StringEntry("last_invoke_id", id), issueNFT, BooleanEntry(((("art_onsale_" + entryID) + "_") + callerAddress), sellStatus), ScriptTransfer(Address(fromBase58String(issuer)), amount, assetId), ScriptTransfer(invoke.caller, 1, idNFT)]
513- }
514- }
515- }
516- }
517- }
518-
519-
520-
521-@Callable(i)
522-func deleteUser (address) = {
523- let callerAddr = toString(addressFromPublicKey(i.callerPublicKey))
524- let id = toBase58String(i.transactionId)
525- if (if ((callerAddr == admin))
526- then true
527- else (callerAddr == admin2))
528- then [DeleteEntry(keyUserDate(address)), DeleteEntry(keyUserAddr(address)), DeleteEntry(keyUserName(address)), DeleteEntry(keyUserDesc(address)), DeleteEntry(keyUserSocial(address)), DeleteEntry(keyUserThumb(address)), StringEntry(keyUserStatus(address), userRemoved), StringEntry("last_invoke_id", id)]
529- else throw("You are not allowed to do that")
530705 }
531706
532707

github/deemru/w8io/169f3d6 
100.17 ms