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:
+
+
+
+ Install the Keplr or Leap wallet extension
+ Configure your wallet for the Sei Atlantic-1 testnet
+ Click "Connect Wallet" in the navigation bar
+ Upload wildlife photos to earn both points and WILD tokens
+
+
+
+ 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 */}
+
+
+
+ )
+}
+
+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 ? (
+
+ ) : (
+
Upload a photo of wildlife to identify and earn rewards
+ )}
+
+
+
+
+
+ {isProcessing ? 'Processing...' : 'Identify Wildlife & Earn Tokens'}
+
+
+ {!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 ? (
+
+ {formatAddress(address)}
+ Wallet
+
+
+ ) : (
+
+ {isConnecting ? 'Connecting...' : 'Connect Wallet'}
+
+ )}
+
+ {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