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

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

+

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

+ +

Sei Blockchain Integration

+ +

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

+ +

+ To get started: +

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

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

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

+ Earn WILD Tokens +

+

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

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

+ Built by Mito Systems - Powered by Sei Network +

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

{analysisState.description}

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

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

+ {analysisState.tokenReward.txHash && ( +

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

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

+ Wildlife Identifier +

+
+

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

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

Upload a photo of wildlife to identify and earn rewards

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

+ {result.message} +

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

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

+ {result.txHash && ( +

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

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