diff --git a/package-lock.json b/package-lock.json index e646c93..3f0802d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,9 +8,12 @@ "name": "wildlife", "version": "0.1.0", "dependencies": { + "@cosmjs/cosmwasm-stargate": "^0.32.2", + "@cosmjs/proto-signing": "^0.32.2", "@fal-ai/client": "^1.2.1", "@google-cloud/vision": "^4.3.2", "@google/generative-ai": "^0.21.0", + "@sei-js/core": "^3.2.0", "@solana/spl-token": "^0.3.8", "@solana/web3.js": "^1.78.4", "@supabase/supabase-js": "^2.49.1", @@ -102,6 +105,186 @@ "node": ">=6.9.0" } }, + "node_modules/@confio/ics23": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@confio/ics23/-/ics23-0.6.8.tgz", + "integrity": "sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==", + "deprecated": "Unmaintained. The codebase for this package was moved to https://github.com/cosmos/ics23 but then the JS implementation was removed in https://github.com/cosmos/ics23/pull/353. Please consult the maintainers of https://github.com/cosmos for further assistance.", + "dependencies": { + "@noble/hashes": "^1.0.0", + "protobufjs": "^6.8.8" + } + }, + "node_modules/@confio/ics23/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/@confio/ics23/node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/@cosmjs/amino": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.32.4.tgz", + "integrity": "sha512-zKYOt6hPy8obIFtLie/xtygCkH9ZROiQ12UHfKsOkWaZfPQUvVbtgmu6R4Kn1tFLI/SRkw7eqhaogmW/3NYu/Q==", + "dependencies": { + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/utils": "^0.32.4" + } + }, + "node_modules/@cosmjs/cosmwasm-stargate": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.32.4.tgz", + "integrity": "sha512-Fuo9BGEiB+POJ5WeRyBGuhyKR1ordvxZGLPuPosFJOH9U0gKMgcjwKMCgAlWFkMlHaTB+tNdA8AifWiHrI7VgA==", + "dependencies": { + "@cosmjs/amino": "^0.32.4", + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/proto-signing": "^0.32.4", + "@cosmjs/stargate": "^0.32.4", + "@cosmjs/tendermint-rpc": "^0.32.4", + "@cosmjs/utils": "^0.32.4", + "cosmjs-types": "^0.9.0", + "pako": "^2.0.2" + } + }, + "node_modules/@cosmjs/crypto": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.32.4.tgz", + "integrity": "sha512-zicjGU051LF1V9v7bp8p7ovq+VyC91xlaHdsFOTo2oVry3KQikp8L/81RkXmUIT8FxMwdx1T7DmFwVQikcSDIw==", + "dependencies": { + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/utils": "^0.32.4", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers-sumo": "^0.7.11" + } + }, + "node_modules/@cosmjs/encoding": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.32.4.tgz", + "integrity": "sha512-tjvaEy6ZGxJchiizzTn7HVRiyTg1i4CObRRaTRPknm5EalE13SV+TCHq38gIDfyUeden4fCuaBVEdBR5+ti7Hw==", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@cosmjs/json-rpc": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.32.4.tgz", + "integrity": "sha512-/jt4mBl7nYzfJ2J/VJ+r19c92mUKF0Lt0JxM3MXEJl7wlwW5haHAWtzRujHkyYMXOwIR+gBqT2S0vntXVBRyhQ==", + "dependencies": { + "@cosmjs/stream": "^0.32.4", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/math": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.32.4.tgz", + "integrity": "sha512-++dqq2TJkoB8zsPVYCvrt88oJWsy1vMOuSOKcdlnXuOA/ASheTJuYy4+oZlTQ3Fr8eALDLGGPhJI02W2HyAQaw==", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@cosmjs/proto-signing": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.32.4.tgz", + "integrity": "sha512-QdyQDbezvdRI4xxSlyM1rSVBO2st5sqtbEIl3IX03uJ7YiZIQHyv6vaHVf1V4mapusCqguiHJzm4N4gsFdLBbQ==", + "dependencies": { + "@cosmjs/amino": "^0.32.4", + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/utils": "^0.32.4", + "cosmjs-types": "^0.9.0" + } + }, + "node_modules/@cosmjs/socket": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.32.4.tgz", + "integrity": "sha512-davcyYziBhkzfXQTu1l5NrpDYv0K9GekZCC9apBRvL1dvMc9F/ygM7iemHjUA+z8tJkxKxrt/YPjJ6XNHzLrkw==", + "dependencies": { + "@cosmjs/stream": "^0.32.4", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stargate": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.32.4.tgz", + "integrity": "sha512-usj08LxBSsPRq9sbpCeVdyLx2guEcOHfJS9mHGCLCXpdAPEIEQEtWLDpEUc0LEhWOx6+k/ChXTc5NpFkdrtGUQ==", + "dependencies": { + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/proto-signing": "^0.32.4", + "@cosmjs/stream": "^0.32.4", + "@cosmjs/tendermint-rpc": "^0.32.4", + "@cosmjs/utils": "^0.32.4", + "cosmjs-types": "^0.9.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/stream": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.32.4.tgz", + "integrity": "sha512-Gih++NYHEiP+oyD4jNEUxU9antoC0pFSg+33Hpp0JlHwH0wXhtD3OOKnzSfDB7OIoEbrzLJUpEjOgpCp5Z+W3A==", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/tendermint-rpc": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.32.4.tgz", + "integrity": "sha512-MWvUUno+4bCb/LmlMIErLypXxy7ckUuzEmpufYYYd9wgbdCXaTaO08SZzyFM5PI8UJ/0S2AmUrgWhldlbxO8mw==", + "dependencies": { + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/json-rpc": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/socket": "^0.32.4", + "@cosmjs/stream": "^0.32.4", + "@cosmjs/utils": "^0.32.4", + "axios": "^1.6.0", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/utils": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.32.4.tgz", + "integrity": "sha512-D1Yc+Zy8oL/hkUkFUL/bwxvuDBzRGpc4cF7/SkdhxX4iHpSLgdOuTt1mhCh9+kl6NQREy9t7SYZ6xeW5gFe60w==" + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -183,6 +366,58 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@ethersproject/bytes": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz", + "integrity": "sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/logger": "^5.8.0" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.8.0.tgz", + "integrity": "sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@ethersproject/bytes": "^5.8.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz", + "integrity": "sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ] + }, "node_modules/@fal-ai/client": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@fal-ai/client/-/client-1.2.1.tgz", @@ -455,6 +690,29 @@ "url": "https://opencollective.com/js-sdsl" } }, + "node_modules/@keplr-wallet/types": { + "version": "0.11.64", + "resolved": "https://registry.npmjs.org/@keplr-wallet/types/-/types-0.11.64.tgz", + "integrity": "sha512-GgzeLDHHfZFyne3O7UIfFHj/uYqVbxAZI31RbBwt460OBbvwQzjrlZwvJW3vieWRAgxKSITjzEDBl2WneFTQdQ==", + "dependencies": { + "axios": "^0.27.2", + "long": "^4.0.0" + } + }, + "node_modules/@keplr-wallet/types/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, + "node_modules/@keplr-wallet/types/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, "node_modules/@msgpack/msgpack": { "version": "3.0.0-beta2", "resolved": "https://registry.npmjs.org/@msgpack/msgpack/-/msgpack-3.0.0-beta2.tgz", @@ -635,6 +893,17 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -679,6 +948,245 @@ "node": ">=12.4.0" } }, + "node_modules/@osmonauts/helpers": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@osmonauts/helpers/-/helpers-0.6.0.tgz", + "integrity": "sha512-l62tWR/0W4R+5wRvMeRK0zlaJ8WZhULKsQAZ7kNzggL0pbndIAV+0BJ/jEBbNletoeGtuV8rpi6Wo+w+RmtZGw==", + "dependencies": { + "@babel/runtime": "^7.18.9", + "@cosmjs/amino": "0.28.13", + "@cosmjs/crypto": "0.28.13", + "@cosmjs/proto-signing": "0.28.13", + "@cosmjs/stargate": "0.28.13", + "cosmjs-types": "0.5.1", + "long": "^5.2.0", + "protobufjs": "^6.11.3" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/amino": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.28.13.tgz", + "integrity": "sha512-IHnH2zGwaY69qT4mVAavr/pfzx6YE+ud1NHJbvVePlbGiz68CXTi5LHR+K0lrKB5mQ7E+ZErWz2mw5U/x+V1wQ==", + "dependencies": { + "@cosmjs/crypto": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/utils": "0.28.13" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/crypto": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.28.13.tgz", + "integrity": "sha512-ynKfM0q/tMBQMHJby6ad8lR3gkgBKaelQhIsCZTjClsnuC7oYT9y3ThSZCUWr7Pa9h0J8ahU2YV2oFWFVWJQzQ==", + "dependencies": { + "@cosmjs/encoding": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/utils": "0.28.13", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.3", + "libsodium-wrappers": "^0.7.6" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/encoding": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.28.13.tgz", + "integrity": "sha512-jtXbAYtV77rLHxoIrjGFsvgGjeTKttuHRv6cvuy3toCZzY7JzTclKH5O2g36IIE4lXwD9xwuhGJ2aa6A3dhNkA==", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/json-rpc": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.28.13.tgz", + "integrity": "sha512-fInSvg7x9P6p+GWqet+TMhrMTM3OWWdLJOGS5w2ryubMjgpR1rLiAx77MdTNkArW+/6sUwku0sN4veM4ENQu6A==", + "dependencies": { + "@cosmjs/stream": "0.28.13", + "xstream": "^11.14.0" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/math": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.28.13.tgz", + "integrity": "sha512-PDpL8W/kbyeWi0mQ2OruyqE8ZUAdxPs1xCbDX3WXJwy2oU+X2UTbkuweJHVpS9CIqmZulBoWQAmlf6t6zr1N/g==", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/proto-signing": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.28.13.tgz", + "integrity": "sha512-nSl/2ZLsUJYz3Ad0RY3ihZUgRHIow2OnYqKsESMu+3RA/jTi9bDYhiBu8mNMHI0xrEJry918B2CyI56pOUHdPQ==", + "dependencies": { + "@cosmjs/amino": "0.28.13", + "@cosmjs/crypto": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/utils": "0.28.13", + "cosmjs-types": "^0.4.0", + "long": "^4.0.0" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/proto-signing/node_modules/cosmjs-types": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.4.1.tgz", + "integrity": "sha512-I7E/cHkIgoJzMNQdFF0YVqPlaTqrqKHrskuSTIqlEyxfB5Lf3WKCajSXVK2yHOfOFfSux/RxEdpMzw/eO4DIog==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/proto-signing/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/socket": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.28.13.tgz", + "integrity": "sha512-lavwGxQ5VdeltyhpFtwCRVfxeWjH5D5mmN7jgx9nuCf3XSFbTcOYxrk2pQ4usenu1Q1KZdL4Yl5RCNrJuHD9Ug==", + "dependencies": { + "@cosmjs/stream": "0.28.13", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/stargate": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.28.13.tgz", + "integrity": "sha512-dVBMazDz8/eActHsRcZjDHHptOBMqvibj5CFgEtZBp22gP6ASzoAUXTlkSVk5FBf4sfuUHoff6st134/+PGMAg==", + "dependencies": { + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/proto-signing": "0.28.13", + "@cosmjs/stream": "0.28.13", + "@cosmjs/tendermint-rpc": "0.28.13", + "@cosmjs/utils": "0.28.13", + "cosmjs-types": "^0.4.0", + "long": "^4.0.0", + "protobufjs": "~6.11.3", + "xstream": "^11.14.0" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/stargate/node_modules/cosmjs-types": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.4.1.tgz", + "integrity": "sha512-I7E/cHkIgoJzMNQdFF0YVqPlaTqrqKHrskuSTIqlEyxfB5Lf3WKCajSXVK2yHOfOFfSux/RxEdpMzw/eO4DIog==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/stargate/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/stream": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.28.13.tgz", + "integrity": "sha512-AnjtfwT8NwPPkd3lhZhjOlOzT0Kn9bgEu2IPOZjQ1nmG2bplsr6TJmnwn0dJxHT7UGtex17h6whKB5N4wU37Wg==", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/tendermint-rpc": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.28.13.tgz", + "integrity": "sha512-GB+ZmfuJIGQm0hsRtLYjeR3lOxF7Z6XyCBR0cX5AAYOZzSEBJjevPgUHD6tLn8zIhvzxaW3/VKnMB+WmlxdH4w==", + "dependencies": { + "@cosmjs/crypto": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/json-rpc": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/socket": "0.28.13", + "@cosmjs/stream": "0.28.13", + "@cosmjs/utils": "0.28.13", + "axios": "^0.21.2", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@osmonauts/helpers/node_modules/@cosmjs/utils": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.28.13.tgz", + "integrity": "sha512-dVeMBiyg+46x7XBZEfJK8yTihphbCFpjVYmLJVqmTsHfJwymQ65cpyW/C+V/LgWARGK8hWQ/aX9HM5Ao8QmMSg==" + }, + "node_modules/@osmonauts/helpers/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/@osmonauts/helpers/node_modules/cosmjs-types": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.5.1.tgz", + "integrity": "sha512-NcC58xUIVLlKdIimWWQAmSlmCjiMrJnuHf4i3LiD8PCextfHR0fT3V5/WlXZZreyMgdmh6ML1zPUfGTbbo3Z5g==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/@osmonauts/helpers/node_modules/cosmjs-types/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/@osmonauts/helpers/node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/@osmonauts/helpers/node_modules/protobufjs/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/@osmonauts/lcd": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@osmonauts/lcd/-/lcd-0.8.0.tgz", + "integrity": "sha512-k7m2gAVnXc0H4m/eTq4z/8A6hFrr3MPS9wnLV4Xu9/K/WYltCnp2PpiObZm+feZUPK/svES6hxIQeO1bODLx8g==", + "dependencies": { + "@babel/runtime": "^7.19.0", + "axios": "0.27.2" + } + }, + "node_modules/@osmonauts/lcd/node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "node_modules/@panva/hkdf": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz", @@ -773,6 +1281,426 @@ "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", "dev": true }, + "node_modules/@sei-js/core": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@sei-js/core/-/core-3.2.1.tgz", + "integrity": "sha512-8pZBYvFhpeUNDH/4WonJNV4yADW7Bqq4RySw8JIsVBC3IBkW53ysKpqf6O0TKOswW6T8E3p39txtajViHYMixw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dependencies": { + "@cosmjs/amino": "^0.29.5", + "@cosmjs/cosmwasm-stargate": "^0.29.5", + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/json-rpc": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "@cosmjs/tendermint-rpc": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "@ethersproject/keccak256": "^5.7.0", + "@keplr-wallet/types": "^0.11.41", + "@noble/secp256k1": "1.7.1", + "@sei-js/proto": "^3.1.0", + "bech32": "^2.0.0", + "buffer": "^6.0.3", + "elliptic": "^6.5.4", + "moment": "^2.30.1", + "process": "^0.11.10", + "readonly-date": "^1.0.0", + "sha.js": "^2.4.11", + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/amino": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.29.5.tgz", + "integrity": "sha512-Qo8jpC0BiziTSUqpkNatBcwtKNhCovUnFul9SlT/74JUCdLYaeG5hxr3q1cssQt++l4LvlcpF+OUXL48XjNjLw==", + "dependencies": { + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/cosmwasm-stargate": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.29.5.tgz", + "integrity": "sha512-TNdSvm2tEE3XMCuxHxquzls56t40hC8qnLeYJWHsY2ECZmRK3KrnpRReEr7N7bLtODToK7X/riYrV0JaYxjrYA==", + "dependencies": { + "@cosmjs/amino": "^0.29.5", + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "@cosmjs/tendermint-rpc": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "cosmjs-types": "^0.5.2", + "long": "^4.0.0", + "pako": "^2.0.2" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/crypto": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.29.5.tgz", + "integrity": "sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ==", + "dependencies": { + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers": "^0.7.6" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/encoding": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.29.5.tgz", + "integrity": "sha512-G4rGl/Jg4dMCw5u6PEZHZcoHnUBlukZODHbm/wcL4Uu91fkn5jVo5cXXZcvs4VCkArVGrEj/52eUgTZCmOBGWQ==", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/encoding/node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/json-rpc": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.29.5.tgz", + "integrity": "sha512-C78+X06l+r9xwdM1yFWIpGl03LhB9NdM1xvZpQHwgCOl0Ir/WV8pw48y3Ez2awAoUBRfTeejPe4KvrE6NoIi/w==", + "dependencies": { + "@cosmjs/stream": "^0.29.5", + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/math": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.29.5.tgz", + "integrity": "sha512-2GjKcv+A9f86MAWYLUkjhw1/WpRl2R1BTb3m9qPG7lzMA7ioYff9jY5SPCfafKdxM4TIQGxXQlYGewQL16O68Q==", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/proto-signing": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.29.5.tgz", + "integrity": "sha512-QRrS7CiKaoETdgIqvi/7JC2qCwCR7lnWaUsTzh/XfRy3McLkEd+cXbKAW3cygykv7IN0VAEIhZd2lyIfT8KwNA==", + "dependencies": { + "@cosmjs/amino": "^0.29.5", + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "cosmjs-types": "^0.5.2", + "long": "^4.0.0" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/socket": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.29.5.tgz", + "integrity": "sha512-5VYDupIWbIXq3ftPV1LkS5Ya/T7Ol/AzWVhNxZ79hPe/mBfv1bGau/LqIYOm2zxGlgm9hBHOTmWGqNYDwr9LNQ==", + "dependencies": { + "@cosmjs/stream": "^0.29.5", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/stargate": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.29.5.tgz", + "integrity": "sha512-hjEv8UUlJruLrYGJcUZXM/CziaINOKwfVm2BoSdUnNTMxGvY/jC1ABHKeZUYt9oXHxEJ1n9+pDqzbKc8pT0nBw==", + "dependencies": { + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stream": "^0.29.5", + "@cosmjs/tendermint-rpc": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "cosmjs-types": "^0.5.2", + "long": "^4.0.0", + "protobufjs": "~6.11.3", + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/stream": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.29.5.tgz", + "integrity": "sha512-TToTDWyH1p05GBtF0Y8jFw2C+4783ueDCmDyxOMM6EU82IqpmIbfwcdMOCAm0JhnyMh+ocdebbFvnX/sGKzRAA==", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/tendermint-rpc": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.29.5.tgz", + "integrity": "sha512-ar80twieuAxsy0x2za/aO3kBr2DFPAXDmk2ikDbmkda+qqfXgl35l9CVAAjKRqd9d+cRvbQyb5M4wy6XQpEV6w==", + "dependencies": { + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/json-rpc": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/socket": "^0.29.5", + "@cosmjs/stream": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "axios": "^0.21.2", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/core/node_modules/@cosmjs/utils": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.29.5.tgz", + "integrity": "sha512-m7h+RXDUxOzEOGt4P+3OVPX7PuakZT3GBmaM/Y2u+abN3xZkziykD/NvedYFvvCCdQo714XcGl33bwifS9FZPQ==" + }, + "node_modules/@sei-js/core/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/@sei-js/core/node_modules/bech32": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" + }, + "node_modules/@sei-js/core/node_modules/cosmjs-types": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.5.2.tgz", + "integrity": "sha512-zxCtIJj8v3Di7s39uN4LNcN3HIE1z0B9Z0SPE8ZNQR0oSzsuSe1ACgxoFkvhkS7WBasCAFcglS11G2hyfd5tPg==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/@sei-js/core/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/@sei-js/core/node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, + "node_modules/@sei-js/proto": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@sei-js/proto/-/proto-3.1.0.tgz", + "integrity": "sha512-TollbfB77pIppO9JOjja/Oo0+n4yOXa0H9yD5SwPPFIrx7Xp5YYrvpVYmZYwf5i0t/ulY8wxbqKfw0sl0geSPw==", + "dependencies": { + "@babel/runtime": "^7.18.9", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stargate": "^0.29.5", + "@cosmjs/tendermint-rpc": "^0.29.5", + "@osmonauts/helpers": "^0.6.0", + "@osmonauts/lcd": "^0.8.0", + "protobufjs": "^6.11.2" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/amino": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.29.5.tgz", + "integrity": "sha512-Qo8jpC0BiziTSUqpkNatBcwtKNhCovUnFul9SlT/74JUCdLYaeG5hxr3q1cssQt++l4LvlcpF+OUXL48XjNjLw==", + "dependencies": { + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/crypto": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.29.5.tgz", + "integrity": "sha512-2bKkaLGictaNL0UipQCL6C1afaisv6k8Wr/GCLx9FqiyFkh9ZgRHDyetD64ZsjnWV/N/D44s/esI+k6oPREaiQ==", + "dependencies": { + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.4", + "libsodium-wrappers": "^0.7.6" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/encoding": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.29.5.tgz", + "integrity": "sha512-G4rGl/Jg4dMCw5u6PEZHZcoHnUBlukZODHbm/wcL4Uu91fkn5jVo5cXXZcvs4VCkArVGrEj/52eUgTZCmOBGWQ==", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/json-rpc": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.29.5.tgz", + "integrity": "sha512-C78+X06l+r9xwdM1yFWIpGl03LhB9NdM1xvZpQHwgCOl0Ir/WV8pw48y3Ez2awAoUBRfTeejPe4KvrE6NoIi/w==", + "dependencies": { + "@cosmjs/stream": "^0.29.5", + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/math": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.29.5.tgz", + "integrity": "sha512-2GjKcv+A9f86MAWYLUkjhw1/WpRl2R1BTb3m9qPG7lzMA7ioYff9jY5SPCfafKdxM4TIQGxXQlYGewQL16O68Q==", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/proto-signing": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.29.5.tgz", + "integrity": "sha512-QRrS7CiKaoETdgIqvi/7JC2qCwCR7lnWaUsTzh/XfRy3McLkEd+cXbKAW3cygykv7IN0VAEIhZd2lyIfT8KwNA==", + "dependencies": { + "@cosmjs/amino": "^0.29.5", + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "cosmjs-types": "^0.5.2", + "long": "^4.0.0" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/socket": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.29.5.tgz", + "integrity": "sha512-5VYDupIWbIXq3ftPV1LkS5Ya/T7Ol/AzWVhNxZ79hPe/mBfv1bGau/LqIYOm2zxGlgm9hBHOTmWGqNYDwr9LNQ==", + "dependencies": { + "@cosmjs/stream": "^0.29.5", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/stargate": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.29.5.tgz", + "integrity": "sha512-hjEv8UUlJruLrYGJcUZXM/CziaINOKwfVm2BoSdUnNTMxGvY/jC1ABHKeZUYt9oXHxEJ1n9+pDqzbKc8pT0nBw==", + "dependencies": { + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/proto-signing": "^0.29.5", + "@cosmjs/stream": "^0.29.5", + "@cosmjs/tendermint-rpc": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "cosmjs-types": "^0.5.2", + "long": "^4.0.0", + "protobufjs": "~6.11.3", + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/stream": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.29.5.tgz", + "integrity": "sha512-TToTDWyH1p05GBtF0Y8jFw2C+4783ueDCmDyxOMM6EU82IqpmIbfwcdMOCAm0JhnyMh+ocdebbFvnX/sGKzRAA==", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/tendermint-rpc": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.29.5.tgz", + "integrity": "sha512-ar80twieuAxsy0x2za/aO3kBr2DFPAXDmk2ikDbmkda+qqfXgl35l9CVAAjKRqd9d+cRvbQyb5M4wy6XQpEV6w==", + "dependencies": { + "@cosmjs/crypto": "^0.29.5", + "@cosmjs/encoding": "^0.29.5", + "@cosmjs/json-rpc": "^0.29.5", + "@cosmjs/math": "^0.29.5", + "@cosmjs/socket": "^0.29.5", + "@cosmjs/stream": "^0.29.5", + "@cosmjs/utils": "^0.29.5", + "axios": "^0.21.2", + "readonly-date": "^1.0.0", + "xstream": "^11.14.0" + } + }, + "node_modules/@sei-js/proto/node_modules/@cosmjs/utils": { + "version": "0.29.5", + "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.29.5.tgz", + "integrity": "sha512-m7h+RXDUxOzEOGt4P+3OVPX7PuakZT3GBmaM/Y2u+abN3xZkziykD/NvedYFvvCCdQo714XcGl33bwifS9FZPQ==" + }, + "node_modules/@sei-js/proto/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/@sei-js/proto/node_modules/cosmjs-types": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.5.2.tgz", + "integrity": "sha512-zxCtIJj8v3Di7s39uN4LNcN3HIE1z0B9Z0SPE8ZNQR0oSzsuSe1ACgxoFkvhkS7WBasCAFcglS11G2hyfd5tPg==", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/@sei-js/proto/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "node_modules/@sei-js/proto/node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "dependencies": { + "@protobufjs/aspromise": "^1.1.2", + "@protobufjs/base64": "^1.1.2", + "@protobufjs/codegen": "^2.0.4", + "@protobufjs/eventemitter": "^1.1.0", + "@protobufjs/fetch": "^1.1.0", + "@protobufjs/float": "^1.0.2", + "@protobufjs/inquire": "^1.1.0", + "@protobufjs/path": "^1.1.2", + "@protobufjs/pool": "^1.1.0", + "@protobufjs/utf8": "^1.1.0", + "@types/long": "^4.0.1", + "@types/node": ">=13.7.0", + "long": "^4.0.0" + }, + "bin": { + "pbjs": "bin/pbjs", + "pbts": "bin/pbts" + } + }, "node_modules/@solana/buffer-layout": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz", @@ -1874,6 +2802,11 @@ } ] }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + }, "node_modules/bigint-buffer": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", @@ -1950,6 +2883,11 @@ "node": ">=8" } }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + }, "node_modules/browser-image-compression": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/browser-image-compression/-/browser-image-compression-2.0.2.tgz", @@ -2377,6 +3315,11 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "license": "MIT" }, + "node_modules/cosmjs-types": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.9.0.tgz", + "integrity": "sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==" + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2492,7 +3435,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2509,7 +3451,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -2644,6 +3585,25 @@ "integrity": "sha512-ck3//9RC+6oss/1Bh9tiAVFy5vfSKbRHAFh7Z3/eTRkEqJeWgymloShB17Vg3Z4nmDNp35vAd1BZ6CMW4Wt6Iw==", "dev": true }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==" + }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", @@ -2738,7 +3698,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -2747,7 +3706,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -3924,7 +4882,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -4013,7 +4970,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -4071,7 +5027,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -4121,6 +5076,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", @@ -4142,6 +5106,16 @@ "node": ">=8" } }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, "node_modules/http-proxy-agent": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", @@ -4809,6 +5783,11 @@ "url": "https://github.com/sponsors/panva" } }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5009,6 +5988,32 @@ "node": ">= 0.8.0" } }, + "node_modules/libsodium": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium/-/libsodium-0.7.15.tgz", + "integrity": "sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw==" + }, + "node_modules/libsodium-sumo": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.15.tgz", + "integrity": "sha512-5tPmqPmq8T8Nikpm1Nqj0hBHvsLFCXvdhBFV7SGOitQPZAA6jso8XoL0r4L7vmfKXr486fiQInvErHtEvizFMw==" + }, + "node_modules/libsodium-wrappers": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-wrappers/-/libsodium-wrappers-0.7.15.tgz", + "integrity": "sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ==", + "dependencies": { + "libsodium": "^0.7.15" + } + }, + "node_modules/libsodium-wrappers-sumo": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.15.tgz", + "integrity": "sha512-aSWY8wKDZh5TC7rMvEdTHoyppVq/1dTSAeAR7H6pzd6QRT3vQWcT5pGwCotLcpPEOLXX6VvqihSPkpEhYAjANA==", + "dependencies": { + "libsodium-sumo": "^0.7.15" + } + }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", @@ -5177,6 +6182,16 @@ "node": ">= 0.6" } }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -5221,6 +6236,14 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "engines": { + "node": "*" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5483,7 +6506,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, "engines": { "node": ">= 0.4" } @@ -5667,6 +6689,11 @@ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "dev": true }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -5982,6 +7009,14 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", "integrity": "sha512-WuxUnVtlWL1OfZFQFuqvnvs6MiAGk9UNsBostyBOB0Is9wb5uRESevA6rnl/rkksXaGX3GzZhPup5d6Vp1nFew==" }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -6134,6 +7169,11 @@ "node": ">=8.10.0" } }, + "node_modules/readonly-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", + "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==" + }, "node_modules/reflect.getprototypeof": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", @@ -6472,6 +7512,18 @@ "node": ">= 0.4" } }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, "node_modules/sharp": { "version": "0.33.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", @@ -7042,6 +8094,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/symbol-observable": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", + "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/tailwindcss": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.3.tgz", @@ -7736,6 +8796,15 @@ } } }, + "node_modules/xstream": { + "version": "11.14.0", + "resolved": "https://registry.npmjs.org/xstream/-/xstream-11.14.0.tgz", + "integrity": "sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==", + "dependencies": { + "globalthis": "^1.0.1", + "symbol-observable": "^2.0.3" + } + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", diff --git a/package.json b/package.json index f7ca1c4..7984330 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,12 @@ "lint": "next lint" }, "dependencies": { + "@cosmjs/cosmwasm-stargate": "^0.32.2", + "@cosmjs/proto-signing": "^0.32.2", "@fal-ai/client": "^1.2.1", "@google-cloud/vision": "^4.3.2", "@google/generative-ai": "^0.21.0", + "@sei-js/core": "^3.2.0", "@solana/spl-token": "^0.3.8", "@solana/web3.js": "^1.78.4", "@supabase/supabase-js": "^2.49.1", diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx index 712c9d2..f866e88 100644 --- a/src/app/about/page.tsx +++ b/src/app/about/page.tsx @@ -38,9 +38,31 @@ const AboutPage = () => {

Users earn a point for each submission. These points are tracked onchain and may be redeemable in the future.

+

Ranger is currently in development; location data is randomly assigned to each image. In the future, we will incorporate verifiable location data in a compliant and privacy preserving manner.

+ +

Sei Blockchain Integration

+ +

+ Connect your Sei wallet to receive token rewards for your wildlife contributions! Each verified wildlife sighting earns you WILD tokens sent directly to your connected wallet on the Atlantic-1 testnet. +

+ +

+ To get started: +

+ +
    +
  1. Install the Keplr or Leap wallet extension
  2. +
  3. Configure your wallet for the Sei Atlantic-1 testnet
  4. +
  5. Click "Connect Wallet" in the navigation bar
  6. +
  7. Upload wildlife photos to earn both points and WILD tokens
  8. +
+ +

+ Rare wildlife sightings earn bonus tokens! Our Wildlife Token (WILD) smart contract on the Sei blockchain ensures transparent and automatic token distribution based on species rarity. +

diff --git a/src/app/api/analyze/route.ts b/src/app/api/analyze/route.ts index 6eee10d..927cd42 100644 --- a/src/app/api/analyze/route.ts +++ b/src/app/api/analyze/route.ts @@ -217,11 +217,12 @@ export async function POST(req: NextRequest): Promise { : "🌿 No wildlife detected in this image. Try uploading a photo of an animal!" }` - // Prepare user response - const userResponse = NextResponse.json({ + // Prepare user response with extra fields for token data we'll add later + const responseData = { description: responseMessage, - isAnimal: visionResult.isAnimal - }) + isAnimal: visionResult.isAnimal, + tokenReward: null + }; // Background processing for animal images if (visionResult.isAnimal) { @@ -275,6 +276,37 @@ export async function POST(req: NextRequest): Promise { visionResult.mainObject ); console.log('Points award result:', pointsResult); + + // Check for Sei wallet connection and award tokens + try { + // Import dynamically to avoid server-side issues with window object + const { awardTokensForSighting } = await import('../../../services/blockchain/tokenRewardService'); + + // Get species from vision result for token amount calculation + const species = visionResult.mainObject || 'animal'; + + // Attempt to award tokens for this wildlife sighting + const tokenResult = await awardTokensForSighting(species); + + // Add token reward info to response if successful + if (tokenResult.success) { + responseData.tokenReward = { + amount: tokenResult.tokenAmount, + txHash: tokenResult.txHash + }; + + console.log('Token reward successful:', tokenResult); + } else if (tokenResult.walletConnected) { + // Wallet was connected but award failed + console.error('Token reward failed:', tokenResult.error); + } else { + // No wallet connected - this is not an error, just informational + console.log('No wallet connected, skipping token reward'); + } + } catch (tokenError) { + console.error('Error processing token reward:', tokenError); + // Continue without token rewards if there's an error + } } } catch (err) { console.error('Failed to award points for image:', err); @@ -296,6 +328,9 @@ export async function POST(req: NextRequest): Promise { console.error('Error in image processing or points awarding:', error); } } + + // Create the final response with all data + const userResponse = NextResponse.json(responseData); return userResponse diff --git a/src/app/earn/page.tsx b/src/app/earn/page.tsx new file mode 100644 index 0000000..350502d --- /dev/null +++ b/src/app/earn/page.tsx @@ -0,0 +1,44 @@ +'use client' + +import React from 'react' +import Navigation from '../../components/Navigation' +import WildlifeIdentifier from '../../components/WildlifeIdentifier' +import { APP_CONFIG, getThemeColors } from '../../config/appConfig' + +const EarnPage: React.FC = (): React.ReactElement => { + const theme = getThemeColors(APP_CONFIG.theme) + + return ( +
+
+ + +
+

+ Earn WILD Tokens +

+

+ Identify wildlife species and earn WILD tokens on the Sei blockchain +

+
+ +
+ {/* Decorative elements */} +
+
+ + +
+ + {/* Info Section */} +
+

+ Built by Mito Systems - Powered by Sei Network +

+
+
+
+ ) +} + +export default EarnPage \ No newline at end of file diff --git a/src/components/ImageAnalysisCard.tsx b/src/components/ImageAnalysisCard.tsx index c89a400..430ac1b 100644 --- a/src/components/ImageAnalysisCard.tsx +++ b/src/components/ImageAnalysisCard.tsx @@ -2,14 +2,25 @@ 'use client' import React, { useState, useRef } from 'react' -import { Leaf } from 'lucide-react' +import { Leaf, Coins } from 'lucide-react' import { APP_CONFIG } from '../config/appConfig' +interface TokenReward { + amount?: number; + txHash?: string; +} + +interface AnalysisResult { + description?: string; + error?: string; + isAnimal?: boolean; + tokenReward?: TokenReward | null; +} interface ImageAnalysisCardProps { title: string description: string - onAnalyze: (file: File) => Promise<{ description?: string, error?: string }> + onAnalyze: (file: File) => Promise } interface AnalysisState { @@ -17,6 +28,7 @@ interface AnalysisState { imageUrl: string | null description: string | null error: string | null + tokenReward: TokenReward | null } const ImageAnalysisCard: React.FC = ({ @@ -30,6 +42,7 @@ const ImageAnalysisCard: React.FC = ({ imageUrl: null, description: null, error: null, + tokenReward: null }) const handleFileSelect = (e: React.ChangeEvent) => { @@ -40,7 +53,8 @@ const ImageAnalysisCard: React.FC = ({ ...analysisState, imageUrl, description: null, - error: null + error: null, + tokenReward: null }) } } @@ -54,6 +68,7 @@ const ImageAnalysisCard: React.FC = ({ ...analysisState, loading: true, error: null, + tokenReward: null }) try { @@ -74,6 +89,7 @@ const ImageAnalysisCard: React.FC = ({ imageUrl: analysisState.imageUrl, description: result.description, error: null, + tokenReward: result.tokenReward || null }) } else { throw new Error('No analysis received') @@ -83,6 +99,7 @@ const ImageAnalysisCard: React.FC = ({ ...analysisState, loading: false, error: error instanceof Error ? error.message : 'Analysis failed', + tokenReward: null }) } } @@ -155,6 +172,23 @@ const ImageAnalysisCard: React.FC = ({ {analysisState.description && (

{analysisState.description}

+ + {/* Token reward notification */} + {analysisState.tokenReward && analysisState.tokenReward.amount && ( +
+ +
+

+ {analysisState.tokenReward.amount} WILD tokens awarded! +

+ {analysisState.tokenReward.txHash && ( +

+ Transaction: {analysisState.tokenReward.txHash.substring(0, 10)}... +

+ )} +
+
+ )}
)}
diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx index 8811c39..961ad52 100644 --- a/src/components/Navigation.tsx +++ b/src/components/Navigation.tsx @@ -5,6 +5,7 @@ import Link from 'next/link' import { usePathname } from 'next/navigation' import { useSession } from 'next-auth/react' import AuthButton from './AuthButton' +import WalletButton from './wallet/WalletButton' const Navigation = () => { const pathname = usePathname() @@ -15,6 +16,7 @@ const Navigation = () => { const baseLinks = [ { href: '/', label: 'Home' }, { href: '/sightings', label: 'Sightings' }, + { href: '/earn', label: 'Earn Tokens' }, { href: '/about', label: 'About' }, ] @@ -51,8 +53,13 @@ const Navigation = () => { -
- +
+
+ +
+
+ +
) diff --git a/src/components/WildlifeIdentifier.tsx b/src/components/WildlifeIdentifier.tsx new file mode 100644 index 0000000..3a5033c --- /dev/null +++ b/src/components/WildlifeIdentifier.tsx @@ -0,0 +1,278 @@ +'use client' + +import React, { useState, useRef } from 'react' +import { Leaf, Coins, AlertCircle } from 'lucide-react' +import { APP_CONFIG } from '../config/appConfig' +import { isWalletConnected, getWalletAddress } from '../services/blockchain/seiService' +import { awardTokensForSighting } from '../services/blockchain/tokenRewardService' + +// Wildlife API endpoint +const API_URL = process.env.NEXT_PUBLIC_WILDLIFE_API_URL || '/api'; + +interface AnalysisResult { + success: boolean; + message: string; + species?: string; + rewardAmount?: string; + txHash?: string; + error?: string; +} + +const WildlifeIdentifier: React.FC = () => { + const fileInputRef = useRef(null); + const [selectedImage, setSelectedImage] = useState(null); + const [previewUrl, setPreviewUrl] = useState(null); + const [isProcessing, setIsProcessing] = useState(false); + const [result, setResult] = useState(null); + const [error, setError] = useState(null); + + // Handle image selection + const handleImageSelect = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (file) { + // Check if the file is an image + if (!file.type.startsWith('image/')) { + setError('Please select an image file'); + return; + } + + // Set the selected file + setSelectedImage(file); + + // Create a preview URL + const imageUrl = URL.createObjectURL(file); + setPreviewUrl(imageUrl); + + // Reset previous results and errors + setResult(null); + setError(null); + } + }; + + // Process the image and get token rewards + const handleAnalyze = async () => { + if (!selectedImage) { + setError('Please select an image first'); + return; + } + + // Check if wallet is connected + if (!isWalletConnected()) { + setError('Please connect your wallet first to receive rewards'); + return; + } + + setIsProcessing(true); + setError(null); + + try { + // Convert image to base64 + const reader = new FileReader(); + reader.readAsDataURL(selectedImage); + + reader.onloadend = async () => { + const base64Image = reader.result as string; + const userAddress = getWalletAddress(); + + if (!userAddress) { + setError('Wallet connection issue. Please reconnect your wallet.'); + setIsProcessing(false); + return; + } + + try { + // Option 1: Using the backend API + if (process.env.NEXT_PUBLIC_USE_WILDLIFE_API === 'true') { + // Send to the backend API + const response = await fetch(`${API_URL}/process-image`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + imageData: base64Image, + userWalletAddress: userAddress, + }), + }); + + const responseData = await response.json(); + setResult(responseData); + } + // Option 2: Direct integration with the blockchain + else { + // Use our existing image analysis code + // This is a simplified example - you should replace this with your actual analysis code + const species = await simulateSpeciesDetection(selectedImage); + + if (species) { + // Award tokens through the Sei blockchain + const rewardResult = await awardTokensForSighting(species); + + if (rewardResult.success) { + setResult({ + success: true, + message: `You've been awarded WILD tokens for identifying a ${species}!`, + species: species, + rewardAmount: rewardResult.tokenAmount?.toString(), + txHash: rewardResult.txHash + }); + } else { + throw new Error(rewardResult.error || 'Failed to award tokens'); + } + } else { + setResult({ + success: false, + message: "No wildlife identified in this image." + }); + } + } + } catch (err) { + setError(err instanceof Error ? err.message : 'Error processing image'); + } finally { + setIsProcessing(false); + } + }; + + reader.onerror = () => { + setError('Error reading the image file'); + setIsProcessing(false); + }; + + } catch (err) { + setError(err instanceof Error ? err.message : 'Error processing image'); + setIsProcessing(false); + } + }; + + // Format token amount (from microWILD to WILD) + const formatTokenAmount = (amount?: string): string => { + if (!amount) return '0'; + return (parseInt(amount) / 1_000_000).toFixed(6); + }; + + // This simulates species detection - replace with your actual image analysis + const simulateSpeciesDetection = async (image: File): Promise => { + // In a real app, you would use your actual image analysis service here + // This is just a simulation for demonstration purposes + const species = ['elephant', 'tiger', 'rhino', 'panda', 'gorilla', 'whale', 'dolphin', 'snow leopard', 'eagle']; + await new Promise(resolve => setTimeout(resolve, 1500)); // Simulate processing time + + // Randomly determine if we detected wildlife (80% chance) + if (Math.random() < 0.8) { + // Return a random species + return species[Math.floor(Math.random() * species.length)]; + } + + return null; // No wildlife detected + }; + + return ( +
+
+
+
+ +

+ Wildlife Identifier +

+
+

+ Identify wildlife species and earn WILD tokens as rewards for conservation +

+
+ +
+ {/* Image Upload Area */} +
+ +
+
+ {previewUrl ? ( + Selected wildlife + ) : ( +

Upload a photo of wildlife to identify and earn rewards

+ )} +
+
+
+ + + + {!isWalletConnected() && ( +
+ + Please connect your wallet to earn token rewards +
+ )} +
+ + {error && ( +
+ {error} +
+ )} + + {result && ( +
+

+ {result.message} +

+ + {/* Token reward notification */} + {result.success && result.species && ( +
+ +
+

+ {result.rewardAmount + ? `${formatTokenAmount(result.rewardAmount)} WILD tokens awarded!` + : 'WILD tokens awarded!'} +

+ {result.txHash && ( +

+ Transaction: + {result.txHash.substring(0, 10)}... + +

+ )} +
+
+ )} +
+ )} +
+
+ ); +}; + +export default WildlifeIdentifier; \ No newline at end of file diff --git a/src/components/wallet/WalletButton.tsx b/src/components/wallet/WalletButton.tsx new file mode 100644 index 0000000..322def3 --- /dev/null +++ b/src/components/wallet/WalletButton.tsx @@ -0,0 +1,118 @@ +// src/components/wallet/WalletButton.tsx +'use client' + +import { useState, useEffect } from 'react' +import { + connectSeiWallet, + disconnectSeiWallet, + isWalletConnected, + getWalletAddress, + WALLET_EVENTS +} from '../../services/blockchain/seiService' + +const WalletButton: React.FC = () => { + const [address, setAddress] = useState(null) + const [isConnecting, setIsConnecting] = useState(false) + const [error, setError] = useState(null) + + useEffect(() => { + // Check if wallet is already connected on component mount + if (isWalletConnected()) { + setAddress(getWalletAddress()) + } + + // Listen for wallet connection events + const handleWalletConnected = (event: CustomEvent) => { + setAddress(event.detail.address) + setError(null) + setIsConnecting(false) + } + + const handleWalletDisconnected = () => { + setAddress(null) + setIsConnecting(false) + } + + const handleWalletError = (event: CustomEvent) => { + setError(typeof event.detail === 'string' + ? event.detail + : 'Failed to connect wallet') + setIsConnecting(false) + } + + // Add event listeners + window.addEventListener(WALLET_EVENTS.CONNECTED, handleWalletConnected as EventListener) + window.addEventListener(WALLET_EVENTS.DISCONNECTED, handleWalletDisconnected) + window.addEventListener(WALLET_EVENTS.ERROR, handleWalletError as EventListener) + + // Clean up event listeners + return () => { + window.removeEventListener(WALLET_EVENTS.CONNECTED, handleWalletConnected as EventListener) + window.removeEventListener(WALLET_EVENTS.DISCONNECTED, handleWalletDisconnected) + window.removeEventListener(WALLET_EVENTS.ERROR, handleWalletError as EventListener) + } + }, []) + + const handleConnect = async () => { + setIsConnecting(true) + setError(null) + + try { + const result = await connectSeiWallet() + if (!result) { + setError('No wallet extension found. Please install Keplr or Leap wallet.') + } + } catch (err) { + console.error('Wallet connection error:', err) + setError('Failed to connect wallet') + } finally { + setIsConnecting(false) + } + } + + const handleDisconnect = () => { + disconnectSeiWallet() + setAddress(null) + } + + // Format address for display + const formatAddress = (addr: string) => { + if (!addr) return '' + return `${addr.substring(0, 6)}...${addr.substring(addr.length - 4)}` + } + + return ( +
+ {address ? ( + + ) : ( + + )} + + {error && ( +
+ {error} +
+ )} +
+ ) +} + +export default WalletButton \ No newline at end of file diff --git a/src/services/blockchain/seiService.ts b/src/services/blockchain/seiService.ts new file mode 100644 index 0000000..ead1f2a --- /dev/null +++ b/src/services/blockchain/seiService.ts @@ -0,0 +1,185 @@ +// src/services/blockchain/seiService.ts +import { SeiWallet } from '@sei-js/core'; +import { AccountData, OfflineSigner } from '@cosmjs/proto-signing'; +import { getSigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate'; + +// Sei network configurations +const NETWORKS = { + testnet: { + chainId: 'atlantic-1', + rpcUrl: 'https://rpc.atlantic-1.sei.io', + restUrl: 'https://rest.atlantic-1.sei.io', + // Smart contract addresses + tokenFactoryAddress: process.env.NEXT_PUBLIC_SEI_TOKEN_FACTORY_ADDRESS || '', + }, +}; + +// Track connected wallet state +let currentWallet: SeiWallet | null = null; +let currentAddress: string | null = null; +let cosmWasmClient: any = null; + +// Custom event for wallet status changes +export const WALLET_EVENTS = { + CONNECTED: 'wallet_connected', + DISCONNECTED: 'wallet_disconnected', + ERROR: 'wallet_error', +}; + +// Dispatch custom events for wallet state changes +const dispatchWalletEvent = (eventName: string, detail?: any) => { + if (typeof window !== 'undefined') { + window.dispatchEvent(new CustomEvent(eventName, { detail })); + } +}; + +/** + * Connect to Sei wallet via Keplr, Leap, or other compatible wallets + */ +export const connectSeiWallet = async (): Promise => { + try { + // Check for Keplr or other Sei compatible wallets + const isBrowserWalletAvailable = typeof window !== 'undefined' && + (window.keplr !== undefined || window.leap !== undefined); + + if (!isBrowserWalletAvailable) { + console.error('No compatible wallet extension found'); + dispatchWalletEvent(WALLET_EVENTS.ERROR, 'No compatible wallet extension found'); + return null; + } + + // Initialize SeiWallet from @sei-js/core + const wallet = await SeiWallet.connectWallet(); + if (!wallet) { + throw new Error('Failed to connect wallet'); + } + + // Get the connected wallet's address + const [account] = await wallet.getAccounts(); + const address = account.address; + + // Store wallet and address + currentWallet = wallet; + currentAddress = address; + + // Initialize CosmWasm client for contract interactions + const network = NETWORKS.testnet; + cosmWasmClient = await getSigningCosmWasmClient( + network.rpcUrl, + wallet as unknown as OfflineSigner + ); + + console.log('Sei wallet connected:', address); + dispatchWalletEvent(WALLET_EVENTS.CONNECTED, { address }); + + return address; + } catch (error) { + console.error('Error connecting Sei wallet:', error); + dispatchWalletEvent(WALLET_EVENTS.ERROR, error); + return null; + } +}; + +/** + * Disconnect the currently connected wallet + */ +export const disconnectSeiWallet = () => { + currentWallet = null; + currentAddress = null; + cosmWasmClient = null; + dispatchWalletEvent(WALLET_EVENTS.DISCONNECTED); + console.log('Sei wallet disconnected'); + return true; +}; + +/** + * Check if wallet is connected + */ +export const isWalletConnected = (): boolean => { + return currentWallet !== null && currentAddress !== null; +}; + +/** + * Get the connected wallet's address + */ +export const getWalletAddress = (): string | null => { + return currentAddress; +}; + +/** + * Award WILD tokens to a user for wildlife sighting + * This interacts with the Wildlife Token smart contract on Sei + */ +export const awardTokensForWildlife = async ( + species: string, + amount: number = 10 +): Promise<{ success: boolean; txHash?: string; error?: string }> => { + try { + if (!isWalletConnected() || !currentAddress || !cosmWasmClient) { + return { + success: false, + error: 'Wallet not connected' + }; + } + + // WILD token contract address from environment or config + const tokenAddress = NETWORKS.testnet.tokenFactoryAddress; + if (!tokenAddress) { + return { + success: false, + error: 'WILD token contract address not configured' + }; + } + + // Execute CosmWasm contract message to award WILD tokens based on species + // The contract determines the actual amount based on species rarity + const result = await cosmWasmClient.execute( + currentAddress, + tokenAddress, + { award_tokens: { recipient: currentAddress, species: species.toLowerCase() } }, + 'auto', + undefined, // memo + [] // funds - no funds sent with this execution + ); + + console.log('WILD tokens awarded successfully:', result); + return { + success: true, + txHash: result.transactionHash + }; + } catch (error) { + console.error('Error awarding WILD tokens:', error); + return { + success: false, + error: error instanceof Error ? error.message : 'Unknown error during token award' + }; + } +}; + +/** + * Get WILD token balance for connected wallet + */ +export const getTokenBalance = async (): Promise => { + try { + if (!isWalletConnected() || !currentAddress || !cosmWasmClient) { + return 0; + } + + const tokenAddress = NETWORKS.testnet.tokenFactoryAddress; + if (!tokenAddress) { + return 0; + } + + // Query WILD token balance from CosmWasm contract + const balance = await cosmWasmClient.queryContractSmart( + tokenAddress, + { balance: { address: currentAddress } } + ); + + // Parse the balance - CosmWasm contracts often return strings for big numbers + return parseInt(balance.balance) || 0; + } catch (error) { + console.error('Error getting WILD token balance:', error); + return 0; + } +}; \ No newline at end of file diff --git a/src/services/blockchain/tokenRewardService.ts b/src/services/blockchain/tokenRewardService.ts new file mode 100644 index 0000000..23ecb58 --- /dev/null +++ b/src/services/blockchain/tokenRewardService.ts @@ -0,0 +1,89 @@ +// src/services/blockchain/tokenRewardService.ts +import { awardTokensForWildlife } from './seiService'; +import { isWalletConnected, getWalletAddress } from './seiService'; + +// Note: These reward amounts are for display purposes only +// The actual reward amounts are determined by the WILD token contract on Sei +export const TOKEN_REWARDS = { + WILDLIFE_SIGHTING: 10, // Base WILD token reward for any wildlife sighting + RARE_SPECIES: 25, // Additional WILD tokens for rare species +}; + +// List of species considered rare for bonus rewards +const RARE_SPECIES = [ + 'elephant', + 'tiger', + 'rhino', + 'panda', + 'gorilla', + 'whale', + 'dolphin', + 'snow leopard', + 'eagle', + // Add more rare species as needed +]; + +/** + * Determine if a species is considered rare + * @param species The detected animal species + * @returns True if the species is considered rare + */ +export const isRareSpecies = (species: string): boolean => { + if (!species) return false; + const normalizedSpecies = species.toLowerCase().trim(); + return RARE_SPECIES.some(rareSpecies => + normalizedSpecies.includes(rareSpecies) + ); +}; + +/** + * Award tokens for a wildlife sighting if wallet is connected + * @param species The detected animal species + * @returns Object containing success status and transaction info + */ +export const awardTokensForSighting = async (species: string): Promise<{ + success: boolean; + tokenAmount?: number; + txHash?: string; + error?: string; + walletConnected: boolean; +}> => { + try { + // Check if wallet is connected + if (!isWalletConnected()) { + return { + success: false, + error: 'No wallet connected', + walletConnected: false + }; + } + + // Calculate token reward amount + const baseReward = TOKEN_REWARDS.WILDLIFE_SIGHTING; + const isRare = isRareSpecies(species); + const rareBonus = isRare ? TOKEN_REWARDS.RARE_SPECIES : 0; + const totalReward = baseReward + rareBonus; + + // Award WILD tokens through Sei contract based on species + const result = await awardTokensForWildlife(species, totalReward); + + if (result.success) { + console.log(`Awarded ${totalReward} tokens for ${species} sighting to wallet ${getWalletAddress()}`); + return { + success: true, + tokenAmount: totalReward, + txHash: result.txHash, + walletConnected: true + }; + } else { + throw new Error(result.error || 'Failed to award tokens'); + } + } catch (error) { + console.error('Error in token reward service:', error); + return { + success: false, + error: error instanceof Error ? error.message : 'Unknown error processing token reward', + walletConnected: true + }; + } +}; \ No newline at end of file diff --git a/src/smart-contracts/.env.example b/src/smart-contracts/.env.example new file mode 100644 index 0000000..bf56017 --- /dev/null +++ b/src/smart-contracts/.env.example @@ -0,0 +1,14 @@ +# Configuration for Sei blockchain integration +# Copy this file to .env and replace with your actual values + +# Sei testnet configuration - Atlantic-1 +NEXT_PUBLIC_SEI_NETWORK="atlantic-1" +NEXT_PUBLIC_SEI_RPC_URL="https://rpc.atlantic-1.sei.io" +NEXT_PUBLIC_SEI_REST_URL="https://rest.atlantic-1.sei.io" + +# WILD token contract address +# Replace with your deployed contract address after deployment +NEXT_PUBLIC_SEI_TOKEN_FACTORY_ADDRESS="sei1..." + +# Optional: Wallet for automated tests (use only for testing) +# SEI_TEST_MNEMONIC="your twelve word mnemonic here only for testing" \ No newline at end of file diff --git a/src/smart-contracts/README.md b/src/smart-contracts/README.md new file mode 100644 index 0000000..f26069d --- /dev/null +++ b/src/smart-contracts/README.md @@ -0,0 +1,55 @@ +# Wildlife Token Smart Contract + +This directory contains the smart contract code for the Wildlife Token (WILD) used in the Wildlife Sightings application. + +## Overview + +The `WildlifeToken.sol` contract is an ERC-20 token designed to be deployed on the Sei EVM. It provides functionality for: + +- Minting tokens as rewards for wildlife documentation +- Setting different reward amounts for various wildlife species +- Managing authorized distributors who can award tokens + +## Deployment Instructions + +To deploy this contract on the Sei EVM: + +1. Install Hardhat or Truffle as your Ethereum development framework +2. Configure your deployment script to target Sei EVM +3. Deploy with an RPC endpoint for Sei testnet (atlantic-1): + - RPC URL: https://rpc.atlantic-1.sei.io + - Chain ID: 1 + +## Contract Configuration + +Before deployment, you may want to customize: + +- The token name and symbol +- Maximum token supply +- Initial token distribution +- Default reward amounts for different species + +## Authorizing the Backend + +After deployment, you'll need to: + +1. Call `setDistributor(backendAddress, true)` to authorize your backend server to distribute tokens +2. Configure the backend with the deployed contract address +3. Update the `.env` file with: + ``` + NEXT_PUBLIC_SEI_TOKEN_FACTORY_ADDRESS=0x... (your deployed contract address) + ``` + +## Security Considerations + +- Only authorized distributors can mint new tokens +- The contract has a capped supply to prevent inflation +- The owner can update reward amounts for different species + +## Testing + +Before mainnet deployment, thoroughly test the contract on Sei testnet: + +1. Test token minting and distribution +2. Verify reward calculations for different species +3. Check authorization controls \ No newline at end of file diff --git a/src/smart-contracts/WildlifeToken.sol b/src/smart-contracts/WildlifeToken.sol new file mode 100644 index 0000000..e33886d --- /dev/null +++ b/src/smart-contracts/WildlifeToken.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol"; +import "@openzeppelin/contracts/access/Ownable.sol"; + +/** + * @title WildlifeToken + * @dev ERC20 token for rewarding wildlife documentation contributions + * To be deployed on Sei Atlantic-1 testnet EVM + */ +contract WildlifeToken is ERC20Capped, Ownable { + // Events + event TokensAwarded(address indexed recipient, uint256 amount, string species); + + // Reward amounts for different wildlife types + mapping(string => uint256) public speciesRewards; + + // List of authorized reward distributors + mapping(address => bool) public authorizedDistributors; + + // Maximum token supply: 100 million tokens + uint256 private constant MAX_SUPPLY = 100_000_000 * 10**18; + + /** + * @dev Constructor that sets up the Wildlife Token + */ + constructor() + ERC20("Wildlife Conservation Token", "WILD") + ERC20Capped(MAX_SUPPLY) + Ownable(msg.sender) + { + // Initialize with base reward values (in tokens, will be multiplied by decimals) + speciesRewards["default"] = 10 * 10**18; // Default reward + + // Rare species receive higher rewards + speciesRewards["elephant"] = 25 * 10**18; + speciesRewards["tiger"] = 25 * 10**18; + speciesRewards["rhino"] = 30 * 10**18; + speciesRewards["panda"] = 25 * 10**18; + speciesRewards["gorilla"] = 25 * 10**18; + speciesRewards["whale"] = 25 * 10**18; + speciesRewards["dolphin"] = 15 * 10**18; + speciesRewards["snow leopard"] = 30 * 10**18; + speciesRewards["eagle"] = 15 * 10**18; + + // Set contract creator as an authorized distributor + authorizedDistributors[msg.sender] = true; + + // Mint initial supply for rewards pool (10% of total supply) + _mint(msg.sender, MAX_SUPPLY / 10); + } + + /** + * @dev Add or update a distributor authorization + * @param distributor Address to authorize or deauthorize + * @param authorized True to authorize, false to deauthorize + */ + function setDistributor(address distributor, bool authorized) external onlyOwner { + authorizedDistributors[distributor] = authorized; + } + + /** + * @dev Set the reward amount for a specific species + * @param species Name of the wildlife species + * @param amount Reward amount in tokens + */ + function setSpeciesReward(string calldata species, uint256 amount) external onlyOwner { + speciesRewards[species] = amount; + } + + /** + * @dev Award tokens to a user for documenting wildlife + * @param recipient Address of the recipient + * @param species Name of the wildlife species documented + * @return Amount of tokens awarded + */ + function awardTokens(address recipient, string calldata species) external returns (uint256) { + // Check if caller is an authorized distributor + require(authorizedDistributors[msg.sender], "Not authorized to distribute tokens"); + + // Get reward amount for the species (or default if not set) + uint256 rewardAmount = speciesRewards[species]; + if (rewardAmount == 0) { + rewardAmount = speciesRewards["default"]; + } + + // Mint tokens to the recipient + _mint(recipient, rewardAmount); + + // Emit event for tracking + emit TokensAwarded(recipient, rewardAmount, species); + + return rewardAmount; + } + + /** + * @dev Override _mint to respect the cap + */ + function _mint(address account, uint256 amount) internal override(ERC20, ERC20Capped) { + ERC20Capped._mint(account, amount); + } +} \ No newline at end of file diff --git a/src/smart-contracts/cosmwasm/README.md b/src/smart-contracts/cosmwasm/README.md new file mode 100644 index 0000000..214dc7b --- /dev/null +++ b/src/smart-contracts/cosmwasm/README.md @@ -0,0 +1,75 @@ +# Wildlife Token CosmWasm Contract + +This directory contains the CosmWasm smart contract code for the Wildlife Token (WILD) used in the Wildlife Sightings application. + +## Overview + +The `wildlife_token.rs` contract is a CW20-compatible token designed for the Sei blockchain. It builds on the standard CW20 token implementation and adds functionality for: + +- Minting tokens as rewards for wildlife documentation +- Setting different reward amounts for various wildlife species +- Managing authorized distributors who can award tokens + +## Deployment Instructions + +To deploy this contract on the Sei Atlantic-1 testnet: + +1. Set up a Rust development environment with CosmWasm +2. Compile the contract to Wasm +3. Deploy the compiled contract using a Sei wallet with: + ``` + sei-cli tx wasm store wildlife_token.wasm --from --chain-id atlantic-1 --gas-prices 0.01usei + ``` +4. Instantiate the deployed contract: + ``` + sei-cli tx wasm instantiate '{"name":"Wildlife Conservation Token","symbol":"WILD","decimals":6}' --from --label "Wildlife Token" --chain-id atlantic-1 + ``` + +## Contract Configuration + +The contract is pre-configured with: + +- Token name: "Wildlife Conservation Token" +- Token symbol: "WILD" +- Decimals: 6 +- Initial supply: 10% of max supply (10,000,000 WILD) +- Default reward: 10 WILD per sighting +- Rare species rewards: 15-30 WILD depending on rarity + +## Authorizing the Backend + +After deployment, you'll need to: + +1. Call the `add_distributor` function to authorize your backend server to distribute tokens +2. Configure the backend with the deployed contract address +3. Update the `.env` file with: + ``` + NEXT_PUBLIC_SEI_TOKEN_FACTORY_ADDRESS=sei1... (your deployed contract address) + ``` + +## Testing + +Before using on the testnet, thoroughly test the contract using: + +1. Unit tests for contract functionality +2. Test token minting and distribution on the Sei testnet +3. Verify reward calculations for different species + +## Contract Messages + +The contract supports the following messages: + +### Execute Messages + +- Standard CW20 messages for transfers, allowances, etc. +- `set_species_reward`: Set the reward amount for a specific species +- `award_tokens`: Mint and send tokens to a user who documented wildlife +- `add_distributor`: Authorize an address to award tokens +- `remove_distributor`: Remove distributor authorization + +### Query Messages + +- Standard CW20 balance and token info queries +- `species_reward`: Get the reward amount for a specific species +- `is_distributor`: Check if an address is authorized to award tokens +- `all_species_rewards`: List all configured species and their reward amounts \ No newline at end of file diff --git a/src/smart-contracts/cosmwasm/wildlife_token.rs b/src/smart-contracts/cosmwasm/wildlife_token.rs new file mode 100644 index 0000000..1017e5c --- /dev/null +++ b/src/smart-contracts/cosmwasm/wildlife_token.rs @@ -0,0 +1,352 @@ +// wildlife_token.rs - CosmWasm contract for Wildlife Token (WILD) +// This is a simplified example of a CosmWasm contract for the Sei blockchain +// To be deployed on Atlantic-1 testnet + +use cosmwasm_std::{ + entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, Uint128, + Addr, +}; +use cw20::{Cw20ExecuteMsg, Cw20ReceiveMsg}; +use cw20_base::contract::{execute as cw20_execute, query as cw20_query}; +use cw20_base::msg::{ExecuteMsg as Cw20ExecuteMsg, QueryMsg as Cw20QueryMsg}; +use cw20_base::state::{MinterData, TokenInfo, TOKEN_INFO}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +// Custom messages for our Wildlife Token contract +#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)] +#[serde(rename_all = "snake_case")] +pub enum ExecuteMsg { + // Standard CW20 messages + Transfer { recipient: String, amount: Uint128 }, + Burn { amount: Uint128 }, + Send { contract: String, amount: Uint128, msg: Binary }, + IncreaseAllowance { spender: String, amount: Uint128, expires: Option }, + DecreaseAllowance { spender: String, amount: Uint128, expires: Option }, + TransferFrom { owner: String, recipient: String, amount: Uint128 }, + BurnFrom { owner: String, amount: Uint128 }, + SendFrom { owner: String, contract: String, amount: Uint128, msg: Binary }, + // Custom Wildlife Token messages + SetSpeciesReward { species: String, amount: Uint128 }, + AwardTokens { recipient: String, species: String }, + AddDistributor { address: String }, + RemoveDistributor { address: String }, +} + +// State for tracking distributors and species rewards +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct WildlifeState { + pub distributors: Vec, + pub species_rewards: HashMap, +} + +// Initialize the contract +#[entry_point] +pub fn instantiate( + deps: DepsMut, + _env: Env, + info: MessageInfo, + msg: InstantiateMsg, +) -> StdResult { + // Initialize CW20 token + let token_info = TokenInfo { + name: "Wildlife Conservation Token".to_string(), + symbol: "WILD".to_string(), + decimals: 6, + total_supply: Uint128::zero(), + mint: Some(MinterData { + minter: info.sender.clone(), + cap: Some(Uint128::from(100_000_000_000_000u128)), // 100 million tokens with 6 decimals + }), + }; + TOKEN_INFO.save(deps.storage, &token_info)?; + + // Initialize wildlife-specific state + let mut species_rewards = HashMap::new(); + + // Set default reward + species_rewards.insert("default".to_string(), Uint128::from(10_000_000u128)); // 10 WILD + + // Set rewards for rare species + species_rewards.insert("elephant".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("tiger".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("rhino".to_string(), Uint128::from(30_000_000u128)); + species_rewards.insert("panda".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("gorilla".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("whale".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("dolphin".to_string(), Uint128::from(15_000_000u128)); + species_rewards.insert("snow leopard".to_string(), Uint128::from(30_000_000u128)); + species_rewards.insert("eagle".to_string(), Uint128::from(15_000_000u128)); + + let wildlife_state = WildlifeState { + distributors: vec![info.sender.clone()], + species_rewards, + }; + + WILDLIFE_STATE.save(deps.storage, &wildlife_state)?; + + // Mint initial supply for rewards pool (10% of max supply) + let initial_supply = Uint128::from(10_000_000_000_000u128); + cw20_execute( + deps, + _env, + info, + Cw20ExecuteMsg::Mint { + recipient: info.sender.to_string(), + amount: initial_supply, + }, + )?; + + Ok(Response::default() + .add_attribute("method", "instantiate") + .add_attribute("token_name", "Wildlife Conservation Token") + .add_attribute("token_symbol", "WILD") + .add_attribute("initial_supply", initial_supply)) +} + +// Execute function for handling messages +#[entry_point] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> StdResult { + match msg { + // For standard CW20 operations, use the base implementation + ExecuteMsg::Transfer { recipient, amount } => { + cw20_execute(deps, env, info, Cw20ExecuteMsg::Transfer { recipient, amount }) + } + ExecuteMsg::Burn { amount } => { + cw20_execute(deps, env, info, Cw20ExecuteMsg::Burn { amount }) + } + ExecuteMsg::Send { contract, amount, msg } => { + cw20_execute(deps, env, info, Cw20ExecuteMsg::Send { contract, amount, msg }) + } + ExecuteMsg::IncreaseAllowance { spender, amount, expires } => { + cw20_execute(deps, env, info, Cw20ExecuteMsg::IncreaseAllowance { spender, amount, expires }) + } + ExecuteMsg::DecreaseAllowance { spender, amount, expires } => { + cw20_execute(deps, env, info, Cw20ExecuteMsg::DecreaseAllowance { spender, amount, expires }) + } + ExecuteMsg::TransferFrom { owner, recipient, amount } => { + cw20_execute(deps, env, info, Cw20ExecuteMsg::TransferFrom { owner, recipient, amount }) + } + ExecuteMsg::BurnFrom { owner, amount } => { + cw20_execute(deps, env, info, Cw20ExecuteMsg::BurnFrom { owner, amount }) + } + ExecuteMsg::SendFrom { owner, contract, amount, msg } => { + cw20_execute(deps, env, info, Cw20ExecuteMsg::SendFrom { owner, contract, amount, msg }) + } + + // Custom wildlife token operations + ExecuteMsg::SetSpeciesReward { species, amount } => { + // Only contract owner can set rewards + let token_info = TOKEN_INFO.load(deps.storage)?; + if let Some(mint) = token_info.mint { + if mint.minter != info.sender { + return Err(cosmwasm_std::StdError::generic_err("Unauthorized")); + } + } else { + return Err(cosmwasm_std::StdError::generic_err("No minter set")); + } + + let mut state = WILDLIFE_STATE.load(deps.storage)?; + state.species_rewards.insert(species.clone(), amount); + WILDLIFE_STATE.save(deps.storage, &state)?; + + Ok(Response::new() + .add_attribute("action", "set_species_reward") + .add_attribute("species", species) + .add_attribute("amount", amount.to_string())) + } + + ExecuteMsg::AwardTokens { recipient, species } => { + // Check if caller is an authorized distributor + let state = WILDLIFE_STATE.load(deps.storage)?; + if !state.distributors.contains(&info.sender) { + return Err(cosmwasm_std::StdError::generic_err("Not authorized to distribute tokens")); + } + + // Get reward amount for the species (or default if not set) + let species_lower = species.to_lowercase(); + let reward_amount = match state.species_rewards.get(&species_lower) { + Some(amount) => *amount, + None => match state.species_rewards.get("default") { + Some(amount) => *amount, + None => return Err(cosmwasm_std::StdError::generic_err("No default reward set")), + }, + }; + + // Get recipient address + let recipient_addr = deps.api.addr_validate(&recipient)?; + + // Mint tokens to the recipient + cw20_execute( + deps, + env, + info, + Cw20ExecuteMsg::Mint { + recipient: recipient_addr.to_string(), + amount: reward_amount, + }, + )?; + + Ok(Response::new() + .add_attribute("action", "award_tokens") + .add_attribute("recipient", recipient) + .add_attribute("species", species) + .add_attribute("amount", reward_amount.to_string())) + } + + ExecuteMsg::AddDistributor { address } => { + // Only contract owner can add distributors + let token_info = TOKEN_INFO.load(deps.storage)?; + if let Some(mint) = token_info.mint { + if mint.minter != info.sender { + return Err(cosmwasm_std::StdError::generic_err("Unauthorized")); + } + } else { + return Err(cosmwasm_std::StdError::generic_err("No minter set")); + } + + let addr = deps.api.addr_validate(&address)?; + let mut state = WILDLIFE_STATE.load(deps.storage)?; + if !state.distributors.contains(&addr) { + state.distributors.push(addr.clone()); + WILDLIFE_STATE.save(deps.storage, &state)?; + } + + Ok(Response::new() + .add_attribute("action", "add_distributor") + .add_attribute("address", address)) + } + + ExecuteMsg::RemoveDistributor { address } => { + // Only contract owner can remove distributors + let token_info = TOKEN_INFO.load(deps.storage)?; + if let Some(mint) = token_info.mint { + if mint.minter != info.sender { + return Err(cosmwasm_std::StdError::generic_err("Unauthorized")); + } + } else { + return Err(cosmwasm_std::StdError::generic_err("No minter set")); + } + + let addr = deps.api.addr_validate(&address)?; + let mut state = WILDLIFE_STATE.load(deps.storage)?; + state.distributors.retain(|x| x != &addr); + WILDLIFE_STATE.save(deps.storage, &state)?; + + Ok(Response::new() + .add_attribute("action", "remove_distributor") + .add_attribute("address", address)) + } + } +} + +// Query function for reading contract state +#[entry_point] +pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult { + match msg { + // For standard CW20 queries, use the base implementation + QueryMsg::Balance { address } => cw20_query(deps, _env, Cw20QueryMsg::Balance { address }), + QueryMsg::TokenInfo {} => cw20_query(deps, _env, Cw20QueryMsg::TokenInfo {}), + QueryMsg::Minter {} => cw20_query(deps, _env, Cw20QueryMsg::Minter {}), + QueryMsg::Allowance { owner, spender } => { + cw20_query(deps, _env, Cw20QueryMsg::Allowance { owner, spender }) + } + QueryMsg::AllAllowances { owner, start_after, limit } => { + cw20_query(deps, _env, Cw20QueryMsg::AllAllowances { owner, start_after, limit }) + } + QueryMsg::AllAccounts { start_after, limit } => { + cw20_query(deps, _env, Cw20QueryMsg::AllAccounts { start_after, limit }) + } + + // Custom wildlife token queries + QueryMsg::SpeciesReward { species } => { + let state = WILDLIFE_STATE.load(deps.storage)?; + let species_lower = species.to_lowercase(); + let reward = match state.species_rewards.get(&species_lower) { + Some(amount) => *amount, + None => match state.species_rewards.get("default") { + Some(amount) => *amount, + None => Uint128::zero(), + }, + }; + to_binary(&SpeciesRewardResponse { species, reward }) + } + + QueryMsg::IsDistributor { address } => { + let state = WILDLIFE_STATE.load(deps.storage)?; + let addr = deps.api.addr_validate(&address)?; + let is_distributor = state.distributors.contains(&addr); + to_binary(&IsDistributorResponse { address, is_distributor }) + } + + QueryMsg::AllSpeciesRewards {} => { + let state = WILDLIFE_STATE.load(deps.storage)?; + let rewards: Vec = state.species_rewards + .iter() + .map(|(species, amount)| SpeciesReward { + species: species.clone(), + reward: *amount, + }) + .collect(); + to_binary(&AllSpeciesRewardsResponse { rewards }) + } + } +} + +// Custom query messages +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +#[serde(rename_all = "snake_case")] +pub enum QueryMsg { + // Standard CW20 queries + Balance { address: String }, + TokenInfo {}, + Minter {}, + Allowance { owner: String, spender: String }, + AllAllowances { owner: String, start_after: Option, limit: Option }, + AllAccounts { start_after: Option, limit: Option }, + // Custom Wildlife Token queries + SpeciesReward { species: String }, + IsDistributor { address: String }, + AllSpeciesRewards {}, +} + +// Query response types +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct SpeciesRewardResponse { + pub species: String, + pub reward: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct IsDistributorResponse { + pub address: String, + pub is_distributor: bool, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct SpeciesReward { + pub species: String, + pub reward: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct AllSpeciesRewardsResponse { + pub rewards: Vec, +} + +// Instantiate message +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct InstantiateMsg { + pub name: String, + pub symbol: String, + pub decimals: u8, +} + +// State variable for wildlife-specific data +pub const WILDLIFE_STATE: Item = Item::new("wildlife_state"); \ No newline at end of file diff --git a/wildlife_token_new/wildlife_token/.cargo/config.toml b/wildlife_token_new/wildlife_token/.cargo/config.toml new file mode 100644 index 0000000..f5659c7 --- /dev/null +++ b/wildlife_token_new/wildlife_token/.cargo/config.toml @@ -0,0 +1,5 @@ +[alias] +wasm = "build --release --lib --target wasm32-unknown-unknown" +unit-test = "test --lib" +schema = "run --bin schema" +integration-test = "test --lib integration_tests" diff --git a/wildlife_token_new/wildlife_token/.circleci/config.yml b/wildlife_token_new/wildlife_token/.circleci/config.yml new file mode 100644 index 0000000..f1368e5 --- /dev/null +++ b/wildlife_token_new/wildlife_token/.circleci/config.yml @@ -0,0 +1,61 @@ +version: 2.1 + +executors: + builder: + docker: + - image: buildpack-deps:trusty + +jobs: + docker-image: + executor: builder + steps: + - checkout + - setup_remote_docker: + docker_layer_caching: true + - run: + name: Build Docker artifact + command: docker build --pull -t "cosmwasm/cw-gitpod-base:${CIRCLE_SHA1}" . + - run: + name: Push application Docker image to docker hub + command: | + if [ "${CIRCLE_BRANCH}" = "master" ]; then + docker tag "cosmwasm/cw-gitpod-base:${CIRCLE_SHA1}" cosmwasm/cw-gitpod-base:latest + docker login --password-stdin -u "$DOCKER_USER" \<<<"$DOCKER_PASS" + docker push cosmwasm/cw-gitpod-base:latest + docker logout + fi + + docker-tagged: + executor: builder + steps: + - checkout + - setup_remote_docker: + docker_layer_caching: true + - run: + name: Push application Docker image to docker hub + command: | + docker tag "cosmwasm/cw-gitpod-base:${CIRCLE_SHA1}" "cosmwasm/cw-gitpod-base:${CIRCLE_TAG}" + docker login --password-stdin -u "$DOCKER_USER" \<<<"$DOCKER_PASS" + docker push + docker logout + +workflows: + version: 2 + test-suite: + jobs: + # this is now a slow process... let's only run on master + - docker-image: + filters: + branches: + only: + - master + - docker-tagged: + filters: + tags: + only: + - /^v.*/ + branches: + ignore: + - /.*/ + requires: + - docker-image diff --git a/wildlife_token_new/wildlife_token/.editorconfig b/wildlife_token_new/wildlife_token/.editorconfig new file mode 100644 index 0000000..3d36f20 --- /dev/null +++ b/wildlife_token_new/wildlife_token/.editorconfig @@ -0,0 +1,11 @@ +root = true + +[*] +indent_style = space +indent_size = 2 +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.rs] +indent_size = 4 diff --git a/wildlife_token_new/wildlife_token/.github/workflows/Basic.yml b/wildlife_token_new/wildlife_token/.github/workflows/Basic.yml new file mode 100644 index 0000000..3890a07 --- /dev/null +++ b/wildlife_token_new/wildlife_token/.github/workflows/Basic.yml @@ -0,0 +1,75 @@ +# Based on https://github.com/actions-rs/example/blob/master/.github/workflows/quickstart.yml + +on: [push, pull_request] + +name: Basic + +jobs: + + test: + name: Test Suite + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: 1.60.0 + target: wasm32-unknown-unknown + override: true + + - name: Run unit tests + uses: actions-rs/cargo@v1 + with: + command: unit-test + args: --locked + env: + RUST_BACKTRACE: 1 + + - name: Compile WASM contract + uses: actions-rs/cargo@v1 + with: + command: wasm + args: --locked + env: + RUSTFLAGS: "-C link-arg=-s" + + lints: + name: Lints + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + + - name: Install stable toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: 1.60.0 + override: true + components: rustfmt, clippy + + - name: Run cargo fmt + uses: actions-rs/cargo@v1 + with: + command: fmt + args: --all -- --check + + - name: Run cargo clippy + uses: actions-rs/cargo@v1 + with: + command: clippy + args: -- -D warnings + + - name: Generate Schema + uses: actions-rs/cargo@v1 + with: + command: schema + args: --locked + + - name: Schema Changes + # fails if any changes not committed + run: git diff --exit-code schema diff --git a/wildlife_token_new/wildlife_token/.github/workflows/Release.yml b/wildlife_token_new/wildlife_token/.github/workflows/Release.yml new file mode 100644 index 0000000..a9d5979 --- /dev/null +++ b/wildlife_token_new/wildlife_token/.github/workflows/Release.yml @@ -0,0 +1,35 @@ +name: release wasm + +on: + release: + types: [created] + +jobs: + release: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v2 + - name: Install cargo-run-script + uses: actions-rs/cargo@v1 + with: + command: install + args: cargo-run-script + - name: Run cargo optimize + uses: actions-rs/cargo@v1 + with: + command: run-script + args: optimize + - name: Get release ID + id: get_release + uses: bruceadams/get-release@v1.2.3 + env: + GITHUB_TOKEN: ${{ github.token }} + - name: Upload optimized wasm + uses: svenstaro/upload-release-action@v2 + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + file: ./artifacts/*.wasm + tag: ${{ github.ref }} + overwrite: true + file_glob: true diff --git a/wildlife_token_new/wildlife_token/.gitignore b/wildlife_token_new/wildlife_token/.gitignore new file mode 100644 index 0000000..9095dea --- /dev/null +++ b/wildlife_token_new/wildlife_token/.gitignore @@ -0,0 +1,16 @@ +# Build results +/target +/schema + +# Cargo+Git helper file (https://github.com/rust-lang/cargo/blob/0.44.1/src/cargo/sources/git/utils.rs#L320-L327) +.cargo-ok + +# Text file backups +**/*.rs.bk + +# macOS +.DS_Store + +# IDEs +*.iml +.idea diff --git a/wildlife_token_new/wildlife_token/Cargo.lock b/wildlife_token_new/wildlife_token/Cargo.lock new file mode 100644 index 0000000..3d37a63 --- /dev/null +++ b/wildlife_token_new/wildlife_token/Cargo.lock @@ -0,0 +1,1035 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + +[[package]] +name = "anyhow" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" + +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64ct" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cosmwasm-crypto" +version = "1.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9c82e56962f0f18c9a292aa59940e03a82ce15ef79b93679d5838bb8143f0df" +dependencies = [ + "digest 0.10.7", + "ed25519-zebra", + "k256 0.13.4", + "rand_core 0.6.4", + "thiserror", +] + +[[package]] +name = "cosmwasm-derive" +version = "1.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b804ff15a0e059c88f85ae0e868cf8c7aba9d61221e46f1ad7250f270628c7" +dependencies = [ + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-schema" +version = "1.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5526ea839acb47bbf8fff031ed9aad86e74d43f77b089255417328c3664367d5" +dependencies = [ + "cosmwasm-schema-derive", + "schemars", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "cosmwasm-schema-derive" +version = "1.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f41b99f41f840765d02ae858956bb52af910755976312082e90493c67db512" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cosmwasm-std" +version = "1.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "197ed654c41885e2d76b23bff8db11b0f9745bfdede0909de9daa564edb19187" +dependencies = [ + "base64", + "cosmwasm-crypto", + "cosmwasm-derive", + "derivative", + "forward_ref", + "hex", + "schemars", + "serde", + "serde-json-wasm", + "sha2 0.10.8", + "thiserror", + "uint", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "cw-multi-test" +version = "0.16.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3a9d62dba95ab262438dfd403bffdca647c6615ef1aa431cdc94c262b09643a" +dependencies = [ + "anyhow", + "cosmwasm-std", + "cw-storage-plus 1.1.0", + "cw-utils 1.0.1", + "derivative", + "itertools", + "k256 0.11.6", + "prost", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw-storage-plus" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b6f91c0b94481a3e9ef1ceb183c37d00764f8751e39b45fc09f4d9b970d469" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-storage-plus" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f0e92a069d62067f3472c62e30adedb4cab1754725c0f2a682b3128d2bf3c79" +dependencies = [ + "cosmwasm-std", + "schemars", + "serde", +] + +[[package]] +name = "cw-utils" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6a84c6c1c0acc3616398eba50783934bd6c964bad6974241eaee3460c8f5b26" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 0.16.0", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw-utils" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c80e93d1deccb8588db03945016a292c3c631e6325d349ebb35d2db6f4f946f7" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw2 1.1.0", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "cw2" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91398113b806f4d2a8d5f8d05684704a20ffd5968bf87e3473e1973710b884ad" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.16.0", + "schemars", + "serde", +] + +[[package]] +name = "cw2" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29ac2dc7a55ad64173ca1e0a46697c31b7a5c51342f55a1e84a724da4eb99908" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 1.1.0", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "cw20" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a45a8794a5dd33b66af34caee52a7beceb690856adcc1682b6e3db88b2cdee62" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-utils 0.16.0", + "schemars", + "serde", +] + +[[package]] +name = "cw20-base" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61d826fa1084d026d0abdb54faa5956972efa3a9053473bfcefb5388960aab69" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-storage-plus 0.16.0", + "cw-utils 0.16.0", + "cw2 0.16.0", + "cw20", + "schemars", + "semver", + "serde", + "thiserror", +] + +[[package]] +name = "der" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "dyn-clone" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" + +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der 0.7.9", + "digest 0.10.7", + "elliptic-curve 0.13.8", + "rfc6979 0.4.0", + "signature 2.2.0", + "spki 0.7.3", +] + +[[package]] +name = "ed25519-zebra" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c24f403d068ad0b359e577a77f92392118be3f3c927538f2bb544a5ecd828c6" +dependencies = [ + "curve25519-dalek", + "hashbrown", + "hex", + "rand_core 0.6.4", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.7", + "ff 0.12.1", + "generic-array", + "group 0.12.1", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1 0.3.0", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct 0.2.0", + "crypto-bigint 0.5.5", + "digest 0.10.7", + "ff 0.13.1", + "generic-array", + "group 0.13.0", + "pkcs8 0.10.2", + "rand_core 0.6.4", + "sec1 0.7.3", + "subtle", + "zeroize", +] + +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "forward_ref" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cbd1169bd7b4a0a20d92b9af7a7e0422888bd38a6f5ec29c1fd8c1558a272e" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff 0.13.1", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "k256" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" +dependencies = [ + "cfg-if", + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.8", +] + +[[package]] +name = "k256" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" +dependencies = [ + "cfg-if", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", + "once_cell", + "sha2 0.10.8", + "signature 2.2.0", +] + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "once_cell" +version = "1.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "pkcs8" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" +dependencies = [ + "der 0.6.1", + "spki 0.6.0", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der 0.7.9", + "spki 0.7.3", +] + +[[package]] +name = "proc-macro2" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "444879275cb4fd84958b1a1d5420d15e6fcf7c235fe47f053c9c2a80aceb6001" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9cc1a3263e07e0bf68e96268f37665207b49560d98739662cdfaae215c720fe" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac", + "zeroize", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "schemars" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fbf2ae1b8bc8e02df939598064d22402220cd5bbcca1c76f7d6a310974d5615" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e265784ad618884abaea0600a9adf15393368d840e0222d101a072f3f7534d" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.100", +] + +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct 0.1.1", + "der 0.6.1", + "generic-array", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct 0.2.0", + "der 0.7.9", + "generic-array", + "pkcs8 0.10.2", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-json-wasm" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e9213a07d53faa0b8dd81e767a54a8188a242fdb9be99ab75ec576a774bfdd7" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.1", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der 0.7.9", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.100", +] + +[[package]] +name = "typenum" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "uint" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" +dependencies = [ + "byteorder", + "crunchy", + "hex", + "static_assertions", +] + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wildlife_token" +version = "0.1.0" +dependencies = [ + "cosmwasm-schema", + "cosmwasm-std", + "cw-multi-test", + "cw-storage-plus 0.16.0", + "cw2 0.16.0", + "cw20", + "cw20-base", + "schemars", + "serde", + "thiserror", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/wildlife_token_new/wildlife_token/Cargo.toml b/wildlife_token_new/wildlife_token/Cargo.toml new file mode 100644 index 0000000..7ead9d9 --- /dev/null +++ b/wildlife_token_new/wildlife_token/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "wildlife_token" +version = "0.1.0" +authors = ["zramsay "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +crate-type = ["cdylib", "rlib"] + +[profile.release] +opt-level = 3 +debug = false +rpath = false +lto = true +debug-assertions = false +codegen-units = 1 +panic = 'abort' +incremental = false +overflow-checks = true + +[features] +# use library feature to disable all instantiate/execute/query exports +library = [] +# Use this to enable backtraces in WASM +backtraces = ["cosmwasm-std/backtraces"] + +[package.metadata.scripts] +optimize = """docker run --rm -v "$(pwd)":/code \ + --mount type=volume,source="$(basename "$(pwd)")_cache",target=/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + cosmwasm/rust-optimizer:0.12.10 +""" + +[dependencies] +cosmwasm-schema = "1.1.9" +cosmwasm-std = { version = "1.1.9", default-features = false } +cw-storage-plus = "0.16.0" +cw2 = "0.16.0" +cw20 = "0.16.0" +cw20-base = { version = "0.16.0", features = ["library"] } +schemars = "0.8.12" +serde = { version = "1.0.152", default-features = false, features = ["derive"] } +thiserror = { version = "1.0.38" } + +[dev-dependencies] +cw-multi-test = "0.16.0" \ No newline at end of file diff --git a/wildlife_token_new/wildlife_token/LICENSE b/wildlife_token_new/wildlife_token/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/wildlife_token_new/wildlife_token/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/wildlife_token_new/wildlife_token/NOTICE b/wildlife_token_new/wildlife_token/NOTICE new file mode 100644 index 0000000..8f0c987 --- /dev/null +++ b/wildlife_token_new/wildlife_token/NOTICE @@ -0,0 +1,13 @@ +Copyright 2025 zramsay + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/wildlife_token_new/wildlife_token/README.md b/wildlife_token_new/wildlife_token/README.md new file mode 100644 index 0000000..f811fef --- /dev/null +++ b/wildlife_token_new/wildlife_token/README.md @@ -0,0 +1,137 @@ +# Wildlife Token (WILD) - CosmWasm Contract + +This is a CosmWasm implementation of the Wildlife Token (WILD) for the Sei blockchain. The token rewards users for identifying wildlife in images, with different species having different reward amounts. + +## Overview + +The Wildlife Token is a CW20-compliant token with additional features for managing species-specific rewards and authorized distributors. + +Key features: +- Standard CW20 token functionality (transfer, allowances, etc.) +- Species-specific reward amounts +- Authorized distributor management +- Minting rewards based on verified wildlife identification + +## Contract Components + +1. **Token Info**: Standard CW20 token with 6 decimals +2. **Species Rewards**: Configurable reward amounts for different wildlife species +3. **Distributors**: Authorized addresses that can award tokens + +## Building and Testing + +```sh +# Build the contract +cargo build + +# Run tests +cargo test + +# Generate schema +cargo schema + +# Create optimized WASM for deployment +# Use an appropriate rust-optimizer version compatible with Atlantic-2 +docker run --rm -v "$(pwd)":/code \ + --mount type=volume,source="$(basename "$(pwd)")_cache",target=/target \ + --mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \ + cosmwasm/rust-optimizer:0.12.6 +``` + +## Deployment to Atlantic-2 Testnet + +To deploy this contract to the Sei Atlantic-2 testnet: + +1. **Install Sei Daemon**: + ```sh + # Install sei daemon based on your OS + # See: https://docs.sei.io/develop/deploy-contracts/deploy-on-sei + ``` + +2. **Store WASM on Chain**: + ```sh + # Set up your wallet + sei-daemon keys add my-wallet + + # Store the WASM on-chain (after optimization) + sei-daemon tx wasm store artifacts/wildlife_token.wasm \ + --from my-wallet \ + --chain-id atlantic-2 \ + --gas auto \ + --gas-adjustment 1.3 \ + --node https://rpc.atlantic-2.seinetwork.io:443 \ + --yes + ``` + +3. **Instantiate the Contract**: + ```sh + # Get the code ID from the store transaction + sei-daemon tx wasm instantiate [CODE_ID] \ + '{"name":"Wildlife Conservation Token","symbol":"WILD","decimals":6}' \ + --label "wildlife-token" \ + --from my-wallet \ + --chain-id atlantic-2 \ + --gas auto \ + --gas-adjustment 1.3 \ + --node https://rpc.atlantic-2.seinetwork.io:443 \ + --yes + ``` + +4. **Contract Interaction Examples**: + ```sh + # Query token info + sei-daemon query wasm contract-state smart [CONTRACT_ADDRESS] '{"token_info":{}}' + + # Add a distributor + sei-daemon tx wasm execute [CONTRACT_ADDRESS] \ + '{"add_distributor":{"address":"sei..."}}' \ + --from my-wallet \ + --chain-id atlantic-2 \ + --gas auto \ + --gas-adjustment 1.3 \ + --node https://rpc.atlantic-2.seinetwork.io:443 \ + --yes + + # Award tokens for a wildlife identification + sei-daemon tx wasm execute [CONTRACT_ADDRESS] \ + '{"award_tokens":{"recipient":"sei...","species":"elephant"}}' \ + --from my-wallet \ + --chain-id atlantic-2 \ + --gas auto \ + --gas-adjustment 1.3 \ + --node https://rpc.atlantic-2.seinetwork.io:443 \ + --yes + ``` + +## Sei Dashboard Deployment + +You can also deploy the contract using the Sei Dashboard available at https://app.atlantic-2.seinetwork.io/: + +1. Navigate to the Contracts section +2. Click "Upload Contract" +3. Select your optimized WASM file +4. After upload, instantiate the contract with the parameters: + ```json + { + "name": "Wildlife Conservation Token", + "symbol": "WILD", + "decimals": 6 + } + ``` +5. Use the dashboard to interact with your contract + +## License + +Copyright 2023 Wildlife Token Team + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. \ No newline at end of file diff --git a/wildlife_token_new/wildlife_token/artifacts/checksums.txt b/wildlife_token_new/wildlife_token/artifacts/checksums.txt new file mode 100644 index 0000000..78ff611 --- /dev/null +++ b/wildlife_token_new/wildlife_token/artifacts/checksums.txt @@ -0,0 +1 @@ +1d9a6b82b201c4f2f691fa03b879266cfb641e0482c223915f684de4431a2c6a wildlife_token.wasm diff --git a/wildlife_token_new/wildlife_token/artifacts/checksums_intermediate.txt b/wildlife_token_new/wildlife_token/artifacts/checksums_intermediate.txt new file mode 100644 index 0000000..00ea518 --- /dev/null +++ b/wildlife_token_new/wildlife_token/artifacts/checksums_intermediate.txt @@ -0,0 +1 @@ +6db20ed197f7a0f1fb402f7d72f2934e2dab9337f979aee4ba0c964802cd04ba /target/wasm32-unknown-unknown/release/wildlife_token.wasm diff --git a/wildlife_token_new/wildlife_token/artifacts/wildlife_token.wasm b/wildlife_token_new/wildlife_token/artifacts/wildlife_token.wasm new file mode 100644 index 0000000..320e10b Binary files /dev/null and b/wildlife_token_new/wildlife_token/artifacts/wildlife_token.wasm differ diff --git a/wildlife_token_new/wildlife_token/src/bin/schema.rs b/wildlife_token_new/wildlife_token/src/bin/schema.rs new file mode 100644 index 0000000..c2a6936 --- /dev/null +++ b/wildlife_token_new/wildlife_token/src/bin/schema.rs @@ -0,0 +1,11 @@ +use cosmwasm_schema::write_api; + +use wildlife_token::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; + +fn main() { + write_api! { + instantiate: InstantiateMsg, + execute: ExecuteMsg, + query: QueryMsg, + } +} diff --git a/wildlife_token_new/wildlife_token/src/contract.rs b/wildlife_token_new/wildlife_token/src/contract.rs new file mode 100644 index 0000000..4dee248 --- /dev/null +++ b/wildlife_token_new/wildlife_token/src/contract.rs @@ -0,0 +1,309 @@ +#[cfg(not(feature = "library"))] +use cosmwasm_std::entry_point; +use cosmwasm_std::{to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult, Uint128}; +use cw2::set_contract_version; +use cw20_base::contract::{execute as cw20_execute, query as cw20_query}; +use cw20_base::msg::{ExecuteMsg as Cw20ExecuteMsg, QueryMsg as Cw20QueryMsg}; +use cw20_base::state::{MinterData, TokenInfo, TOKEN_INFO}; +use std::collections::HashMap; + +use crate::error::ContractError; +use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg, SpeciesRewardResponse, IsDistributorResponse, AllSpeciesRewardsResponse, SpeciesReward}; +use crate::state::{WildlifeState, WILDLIFE_STATE}; + +// version info for migration info +const CONTRACT_NAME: &str = "crates.io:wildlife_token"; +const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn instantiate( + deps: DepsMut, + _env: Env, + info: MessageInfo, + msg: InstantiateMsg, +) -> Result { + set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; + + // Initialize CW20 token + let token_info = TokenInfo { + name: msg.name.clone(), + symbol: msg.symbol.clone(), + decimals: msg.decimals, + total_supply: Uint128::zero(), + mint: Some(MinterData { + minter: info.sender.clone(), + cap: Some(Uint128::from(100_000_000_000_000u128)), // 100 million tokens with 6 decimals + }), + }; + TOKEN_INFO.save(deps.storage, &token_info)?; + + // Initialize wildlife-specific state + let mut species_rewards = HashMap::new(); + + // Set default reward + species_rewards.insert("default".to_string(), Uint128::from(10_000_000u128)); // 10 WILD + + // Set rewards for rare species + species_rewards.insert("elephant".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("tiger".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("rhino".to_string(), Uint128::from(30_000_000u128)); + species_rewards.insert("panda".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("gorilla".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("whale".to_string(), Uint128::from(25_000_000u128)); + species_rewards.insert("dolphin".to_string(), Uint128::from(15_000_000u128)); + species_rewards.insert("snow leopard".to_string(), Uint128::from(30_000_000u128)); + species_rewards.insert("eagle".to_string(), Uint128::from(15_000_000u128)); + + let wildlife_state = WildlifeState { + distributors: vec![info.sender.clone()], + species_rewards, + }; + + WILDLIFE_STATE.save(deps.storage, &wildlife_state)?; + + // Mint initial supply for rewards pool (10% of max supply) + let initial_supply = Uint128::from(10_000_000_000_000u128); + cw20_execute( + deps, + _env, + info.clone(), + Cw20ExecuteMsg::Mint { + recipient: info.sender.to_string(), + amount: initial_supply, + }, + )?; + + Ok(Response::new() + .add_attribute("method", "instantiate") + .add_attribute("token_name", msg.name) + .add_attribute("token_symbol", msg.symbol) + .add_attribute("initial_supply", initial_supply.to_string())) +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn execute( + deps: DepsMut, + env: Env, + info: MessageInfo, + msg: ExecuteMsg, +) -> Result { + match msg { + // For standard CW20 operations, use the base implementation + ExecuteMsg::Transfer { recipient, amount } => { + Ok(cw20_execute(deps, env, info, Cw20ExecuteMsg::Transfer { recipient, amount })?) + } + ExecuteMsg::Burn { amount } => { + Ok(cw20_execute(deps, env, info, Cw20ExecuteMsg::Burn { amount })?) + } + ExecuteMsg::Send { contract, amount, msg } => { + Ok(cw20_execute(deps, env, info, Cw20ExecuteMsg::Send { contract, amount, msg })?) + } + ExecuteMsg::IncreaseAllowance { spender, amount, expires } => { + Ok(cw20_execute(deps, env, info, Cw20ExecuteMsg::IncreaseAllowance { spender, amount, expires })?) + } + ExecuteMsg::DecreaseAllowance { spender, amount, expires } => { + Ok(cw20_execute(deps, env, info, Cw20ExecuteMsg::DecreaseAllowance { spender, amount, expires })?) + } + ExecuteMsg::TransferFrom { owner, recipient, amount } => { + Ok(cw20_execute(deps, env, info, Cw20ExecuteMsg::TransferFrom { owner, recipient, amount })?) + } + ExecuteMsg::BurnFrom { owner, amount } => { + Ok(cw20_execute(deps, env, info, Cw20ExecuteMsg::BurnFrom { owner, amount })?) + } + ExecuteMsg::SendFrom { owner, contract, amount, msg } => { + Ok(cw20_execute(deps, env, info, Cw20ExecuteMsg::SendFrom { owner, contract, amount, msg })?) + } + + // Custom wildlife token operations + ExecuteMsg::SetSpeciesReward { species, amount } => { + // Only contract owner can set rewards + let token_info = TOKEN_INFO.load(deps.storage)?; + if let Some(mint) = token_info.mint { + if mint.minter != info.sender { + return Err(ContractError::Unauthorized {}); + } + } else { + return Err(ContractError::NoMinterSet {}); + } + + let mut state = WILDLIFE_STATE.load(deps.storage)?; + state.species_rewards.insert(species.clone(), amount); + WILDLIFE_STATE.save(deps.storage, &state)?; + + Ok(Response::new() + .add_attribute("action", "set_species_reward") + .add_attribute("species", species) + .add_attribute("amount", amount.to_string())) + } + + ExecuteMsg::AwardTokens { recipient, species } => { + // Check if caller is an authorized distributor + let state = WILDLIFE_STATE.load(deps.storage)?; + if !state.distributors.contains(&info.sender) { + return Err(ContractError::NotAuthorizedDistributor {}); + } + + // Get reward amount for the species (or default if not set) + let species_lower = species.to_lowercase(); + let reward_amount = match state.species_rewards.get(&species_lower) { + Some(amount) => *amount, + None => match state.species_rewards.get("default") { + Some(amount) => *amount, + None => return Err(ContractError::NoDefaultReward {}), + }, + }; + + // Get recipient address + let recipient_addr = deps.api.addr_validate(&recipient)?; + + // Mint tokens to the recipient + cw20_execute( + deps, + env, + info, + Cw20ExecuteMsg::Mint { + recipient: recipient_addr.to_string(), + amount: reward_amount, + }, + )?; + + Ok(Response::new() + .add_attribute("action", "award_tokens") + .add_attribute("recipient", recipient) + .add_attribute("species", species) + .add_attribute("amount", reward_amount.to_string())) + } + + ExecuteMsg::AddDistributor { address } => { + // Only contract owner can add distributors + let token_info = TOKEN_INFO.load(deps.storage)?; + if let Some(mint) = token_info.mint { + if mint.minter != info.sender { + return Err(ContractError::Unauthorized {}); + } + } else { + return Err(ContractError::NoMinterSet {}); + } + + let addr = deps.api.addr_validate(&address)?; + let mut state = WILDLIFE_STATE.load(deps.storage)?; + if !state.distributors.contains(&addr) { + state.distributors.push(addr.clone()); + WILDLIFE_STATE.save(deps.storage, &state)?; + } + + Ok(Response::new() + .add_attribute("action", "add_distributor") + .add_attribute("address", address)) + } + + ExecuteMsg::RemoveDistributor { address } => { + // Only contract owner can remove distributors + let token_info = TOKEN_INFO.load(deps.storage)?; + if let Some(mint) = token_info.mint { + if mint.minter != info.sender { + return Err(ContractError::Unauthorized {}); + } + } else { + return Err(ContractError::NoMinterSet {}); + } + + let addr = deps.api.addr_validate(&address)?; + let mut state = WILDLIFE_STATE.load(deps.storage)?; + state.distributors.retain(|x| x != &addr); + WILDLIFE_STATE.save(deps.storage, &state)?; + + Ok(Response::new() + .add_attribute("action", "remove_distributor") + .add_attribute("address", address)) + } + } +} + +#[cfg_attr(not(feature = "library"), entry_point)] +pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { + match msg { + // For standard CW20 queries, use the base implementation + QueryMsg::Balance { address } => cw20_query(deps, env, Cw20QueryMsg::Balance { address }), + QueryMsg::TokenInfo {} => cw20_query(deps, env, Cw20QueryMsg::TokenInfo {}), + QueryMsg::Minter {} => cw20_query(deps, env, Cw20QueryMsg::Minter {}), + QueryMsg::Allowance { owner, spender } => { + cw20_query(deps, env, Cw20QueryMsg::Allowance { owner, spender }) + } + QueryMsg::AllAllowances { owner, start_after, limit } => { + cw20_query(deps, env, Cw20QueryMsg::AllAllowances { owner, start_after, limit }) + } + QueryMsg::AllAccounts { start_after, limit } => { + cw20_query(deps, env, Cw20QueryMsg::AllAccounts { start_after, limit }) + } + + // Custom wildlife token queries + QueryMsg::SpeciesReward { species } => { + let state = WILDLIFE_STATE.load(deps.storage)?; + let species_lower = species.to_lowercase(); + let reward = match state.species_rewards.get(&species_lower) { + Some(amount) => *amount, + None => match state.species_rewards.get("default") { + Some(amount) => *amount, + None => Uint128::zero(), + }, + }; + to_binary(&SpeciesRewardResponse { species, reward }) + } + + QueryMsg::IsDistributor { address } => { + let state = WILDLIFE_STATE.load(deps.storage)?; + let addr = deps.api.addr_validate(&address)?; + let is_distributor = state.distributors.contains(&addr); + to_binary(&IsDistributorResponse { address, is_distributor }) + } + + QueryMsg::AllSpeciesRewards {} => { + let state = WILDLIFE_STATE.load(deps.storage)?; + let rewards: Vec = state.species_rewards + .iter() + .map(|(species, amount)| SpeciesReward { + species: species.clone(), + reward: *amount, + }) + .collect(); + to_binary(&AllSpeciesRewardsResponse { rewards }) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; + use cosmwasm_std::{coins, from_binary}; + + #[test] + fn proper_initialization() { + let mut deps = mock_dependencies(); + + let msg = InstantiateMsg { + name: "Wildlife Conservation Token".to_string(), + symbol: "WILD".to_string(), + decimals: 6, + }; + let info = mock_info("creator", &coins(1000, "earth")); + + // we can just call .unwrap() to assert this was a success + let res = instantiate(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); + assert_eq!(0, res.messages.len()); + + // Check token info + let res = query(deps.as_ref(), mock_env(), QueryMsg::TokenInfo {}).unwrap(); + let token_info: cw20::TokenInfoResponse = from_binary(&res).unwrap(); + assert_eq!("Wildlife Conservation Token", token_info.name); + assert_eq!("WILD", token_info.symbol); + assert_eq!(6, token_info.decimals); + assert_eq!(Uint128::from(10_000_000_000_000u128), token_info.total_supply); + + // Check creator is a distributor + let res = query(deps.as_ref(), mock_env(), QueryMsg::IsDistributor { address: "creator".to_string() }).unwrap(); + let distributor: IsDistributorResponse = from_binary(&res).unwrap(); + assert!(distributor.is_distributor); + } +} \ No newline at end of file diff --git a/wildlife_token_new/wildlife_token/src/error.rs b/wildlife_token_new/wildlife_token/src/error.rs new file mode 100644 index 0000000..6e1c77e --- /dev/null +++ b/wildlife_token_new/wildlife_token/src/error.rs @@ -0,0 +1,23 @@ +use cosmwasm_std::StdError; +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum ContractError { + #[error("{0}")] + Std(#[from] StdError), + + #[error("{0}")] + Cw20Error(#[from] cw20_base::ContractError), + + #[error("Unauthorized")] + Unauthorized {}, + + #[error("Not authorized to distribute tokens")] + NotAuthorizedDistributor {}, + + #[error("No default reward set")] + NoDefaultReward {}, + + #[error("No minter set")] + NoMinterSet {}, +} \ No newline at end of file diff --git a/wildlife_token_new/wildlife_token/src/helpers.rs b/wildlife_token_new/wildlife_token/src/helpers.rs new file mode 100644 index 0000000..cad7733 --- /dev/null +++ b/wildlife_token_new/wildlife_token/src/helpers.rs @@ -0,0 +1,27 @@ +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +use cosmwasm_std::{to_binary, Addr, CosmosMsg, StdResult, WasmMsg}; + +use crate::msg::ExecuteMsg; + +/// CwTemplateContract is a wrapper around Addr that provides a lot of helpers +/// for working with this. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq, JsonSchema)] +pub struct CwTemplateContract(pub Addr); + +impl CwTemplateContract { + pub fn addr(&self) -> Addr { + self.0.clone() + } + + pub fn call>(&self, msg: T) -> StdResult { + let msg = to_binary(&msg.into())?; + Ok(WasmMsg::Execute { + contract_addr: self.addr().into(), + msg, + funds: vec![], + } + .into()) + } +} \ No newline at end of file diff --git a/wildlife_token_new/wildlife_token/src/lib.rs b/wildlife_token_new/wildlife_token/src/lib.rs new file mode 100644 index 0000000..233dbf5 --- /dev/null +++ b/wildlife_token_new/wildlife_token/src/lib.rs @@ -0,0 +1,7 @@ +pub mod contract; +mod error; +pub mod helpers; +pub mod msg; +pub mod state; + +pub use crate::error::ContractError; diff --git a/wildlife_token_new/wildlife_token/src/msg.rs b/wildlife_token_new/wildlife_token/src/msg.rs new file mode 100644 index 0000000..02b95f1 --- /dev/null +++ b/wildlife_token_new/wildlife_token/src/msg.rs @@ -0,0 +1,79 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{Binary, Uint128}; +use cw20::Expiration; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[cw_serde] +pub struct InstantiateMsg { + pub name: String, + pub symbol: String, + pub decimals: u8, +} + +#[cw_serde] +pub enum ExecuteMsg { + // Standard CW20 messages + Transfer { recipient: String, amount: Uint128 }, + Burn { amount: Uint128 }, + Send { contract: String, amount: Uint128, msg: Binary }, + IncreaseAllowance { spender: String, amount: Uint128, expires: Option }, + DecreaseAllowance { spender: String, amount: Uint128, expires: Option }, + TransferFrom { owner: String, recipient: String, amount: Uint128 }, + BurnFrom { owner: String, amount: Uint128 }, + SendFrom { owner: String, contract: String, amount: Uint128, msg: Binary }, + // Custom Wildlife Token messages + SetSpeciesReward { species: String, amount: Uint128 }, + AwardTokens { recipient: String, species: String }, + AddDistributor { address: String }, + RemoveDistributor { address: String }, +} + +#[cw_serde] +#[derive(QueryResponses)] +pub enum QueryMsg { + // Standard CW20 queries + #[returns(cw20::BalanceResponse)] + Balance { address: String }, + #[returns(cw20::TokenInfoResponse)] + TokenInfo {}, + #[returns(Option)] + Minter {}, + #[returns(cw20::AllowanceResponse)] + Allowance { owner: String, spender: String }, + #[returns(cw20::AllAllowancesResponse)] + AllAllowances { owner: String, start_after: Option, limit: Option }, + #[returns(cw20::AllAccountsResponse)] + AllAccounts { start_after: Option, limit: Option }, + // Custom Wildlife Token queries + #[returns(SpeciesRewardResponse)] + SpeciesReward { species: String }, + #[returns(IsDistributorResponse)] + IsDistributor { address: String }, + #[returns(AllSpeciesRewardsResponse)] + AllSpeciesRewards {}, +} + +// Query response types +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct SpeciesRewardResponse { + pub species: String, + pub reward: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct IsDistributorResponse { + pub address: String, + pub is_distributor: bool, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct SpeciesReward { + pub species: String, + pub reward: Uint128, +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct AllSpeciesRewardsResponse { + pub rewards: Vec, +} \ No newline at end of file diff --git a/wildlife_token_new/wildlife_token/src/state.rs b/wildlife_token_new/wildlife_token/src/state.rs new file mode 100644 index 0000000..1779c7b --- /dev/null +++ b/wildlife_token_new/wildlife_token/src/state.rs @@ -0,0 +1,15 @@ +use cosmwasm_std::{Addr, Uint128}; +use cw_storage_plus::Item; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; + +// State for tracking distributors and species rewards +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] +pub struct WildlifeState { + pub distributors: Vec, + pub species_rewards: HashMap, +} + +// State variable for wildlife-specific data +pub const WILDLIFE_STATE: Item = Item::new("wildlife_state"); \ No newline at end of file