diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 000000000..414a345dd --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,28 @@ +name: Create Release + +on: + push: + tags: + - 'v*' + +jobs: + create-release: + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - name: tests + uses: actions/checkout@v3 + - run: cargo install just + working-directory: smart-contracts + - run: cargo check + working-directory: smart-contracts/osmosis + - name: Compile contracts + run: just workspace-optimize + working-directory: smart-contracts/osmosis + - name: Create release + uses: ncipollo/release-action@v1 + with: + artifacts: "smart-contracts/osmosis/artifacts/*.wasm, smart-contracts/osmosis/artifacts/checksums.txt" + artifactErrorsFailBuild: "true" + generateReleaseNotes: "true" diff --git a/DEV_GUIDELINES.md b/DEV_GUIDELINES.md index 88a5956a3..225a72195 100644 --- a/DEV_GUIDELINES.md +++ b/DEV_GUIDELINES.md @@ -19,3 +19,19 @@ tbd In order to balance tracking of our progress and speed of development we use the following rules for unplanned works that gets identified during a sprint: * fix takes less than 1h and you address it immediately: no ticket required * fix takes more than 1h or you don't address it immediately: create a ticket + +## Releases + +### Smart contracts +The following steps are required to release smart contracts: +1. Create a new release: + * Make sure you have the latest state: `git checkout main && git pull` + * Create a tag: `git tag -a "" -m""` (TAG should be of the form v[0-9]+.[0-9]+.[0-9]+) + * Push tag: `git push origin ` +2. Upload code through multisig (This can only be done by the multisig-members, please sync with them): + * Create signed message: `bash scripts/generate_signed_upload_tx.sh `, where and are the names of your key, resp. the multisig key, registered with `osmosisd`. + * Collect signed messages from coworkers, when you have enough: `bash scripts/upload_through_multisig.sh " "` +3. Create proposal to instantiate or migrate contracts on [DAODAO](https://daodao.zone/dao/osmo12ry93err6s2ekg02ekslucwx8n3pxm3y7zxz3l6w8zuhex984k5ss4ltl6/proposals). +4. After the proposal did receive enough votes, it can be executed. +5. Please make sure that all instances of a contract are migrated. You can find a list of contracts [here](smart-contracts/contracts.json). The easiest way to propose the migration of all contracts in that list is by adjusting `scripts/propose_cl_vault_migration` and executing `node scripts/propose_cl_vault_migration.js` from the repo root directory. +6. Update versions and deployment dates in the list of contracts. This can be done with the help of `scripts/update_contracts_list.js`. \ No newline at end of file diff --git a/SCM.md b/SCM.md deleted file mode 100644 index f3a7d61a7..000000000 --- a/SCM.md +++ /dev/null @@ -1,128 +0,0 @@ -# Quasar Source Code Management - -## General considerations - -Quasar development team follows a light git flow approach for source control management. It is light in the sense that new code is merged directly into the `main` branch instead of an intermediary `dev` branch. - -The `main` branch reflects the most recent stable state of the application code. -Anything that merges to `main` is a candidate for release. - -## Pull-requests - -Features or bug fixes are merged frequently to the `main` branch via pull-requests (PR) and mandatory code review. - -All pull-requests should be merged with a forced merge commit, this helps for traceability as **github** will insert details about the pull-request in the commit message. The Github repo is configured to enforce this. - -As much as possible, pull-requests should be rebased onto `main` before merging, this helps in creating a clean and straight history for the `main` branch. - -### Review process - -All pull-requests on **github** have to be approved (after review) before they can be merged. - -When creating a PR, do not assign any reviewers yet. Assigning some people or all people to reviewing a PR often leads to planning issues and lack of ownership for the reviewing task. - -Instead, discuss with the development team about the review (at standup) and ask who can do it. One someone is appointed reviewer, the author update the merge-request with the reviewer's name. - -Usually, one reviewer is sufficient. However, if the work requires more specific knowledge, the author can ask for more than one person to review. The reviewer can also appoint someone else if agreed. - -### Pull-request review material - -[Official Github documentation](https://docs.github.com/en/pull-requests) -[Pull-requests review best practices](https://rewind.com/blog/best-practices-for-reviewing-pull-requests-in-github/) -["Semi-linear" or "Rebase, merge" strategy](https://stackoverflow.com/questions/59714347/semi-linear-merge) - -## Feature & bugfix workflow - -New code can be added via either a **feature** or **bugfix** branch, using the `feature/` or `bugfix/` branch name prefix respectively, followed by a sentence-like description of the feature or bugfix separated by underscores (i.e `feature/my_feature_desc`). - -Example: create a new feature branch out of `main` - -```bash -git checkout main # assuming not on main already -git pull # make sure main is in sync with remote -git checkout -b feature/abc_123 # create the new branch -``` - -Usually, a single developer will work on a feature branch, so it is fine to re-write the history in these branch (with `git rebase` for instance). In practice it can be used when new code has been merged to `main` in the meantime. - -Example: sync new code from `main` via rebase: - -```bash -git fetch --all # fetch new code from remote origin -git rebase origin/main # rebase current branch on top of new code -``` - -If developers work on a feature together, they can individually branch off from the feature branch, as long as the merge is done via either a squash commit or a fast-forward commit (`--ff-only`). -By doing this, the feature branch will still be a single series of commits (no intermediate branching will be visible) and therefore the clear history visibility will be preserved. - -### Visual example - -``` -* 0d54d68 - (3 seconds ago) Merge branch 'bugfix/bug_1' - Alice (HEAD -> main) -|\ -| * 912ce23 - (15 seconds ago) Fix 3 - Alice (bugfix/bug_1) -| * d988e05 - (26 seconds ago) Fix 2 - Alice -| * e9cf5d9 - (65 seconds ago) Fix 1 - Alice -|/ -* 736087f - (4 minutes ago) Merge branch 'feature/feature_1' - Bob -|\ -| * b7e26f3 - (5 minutes ago) Update README with 2 - Bob (feature/feature_1) -| * 0b085c6 - (5 minutes ago) Update README with 1 - Bob -|/ -* 9460178 - (8 minutes ago) Init - Alice -``` - -## Release process - -At any point, on the `main` branch, a commit can be selected for release. For that a git tag needs to be created (see conventions). - -This new git tag can be used to triggers automated CI/CD workflows that will build the release artifacts, publish and deploy them. The tag can also be used for versioning the artifacts (see versioning conventions). - -If release notes and other documentation needs to be updated prior to releasing, it should be done via a **feature** branch and merged to `main`. This merge commit will be the one to be tagged to represent the new release. - -Release tags can be created directly from the Github interface, by selecting the proper commit, or via command-line on a developer's machine as follows: - -```bash -git checkout main # assuming not on main already -git pull # make sure main is in sync with remote -git tag v2.0 # create the new tag -git push origin v2.0 # push tag to remote -``` - -### Hotfix workflow - -If a bug needs to be fixed on a version already released, a branch can be created out of the release tag, with the prefix `release/`. - -Commits can then be cherry-picked to this new branch, if a fix is already available on `main`, or directly in the new branch (decide if we need a special **hotfix** branch here with mandatory PR review). - -Example: create a hotfix on existing release v2.0 - -```bash -git checkout -b release/v2.0 v2.0 # create release branch out of tag -git push -u origin release/v2.0 # push new branch to remote -# do the hotfix work -git add . # make sure main is in sync with remote -git commit -m "hotfix abc" # create the new tag -git push # push commit to remote release branch -``` - -### Visual example - -``` -* 9b470d3 - (8 minutes ago) Merge branch 'feature/feature_43' - Alice -|\ -| * 6e4fe81 - (8 minutes ago) Work on feature_3 - Alice (feature/feature_43) -|/ -| * b80093a - (3 minutes ago) hotfix 2 - Bob (release/v2.0) -| * 981ca74 - (4 minutes ago) hotfix 1 - Bob -|/ -* 5522161 - (9 minutes ago) Merge branch 'feature/release_v2.0_prep' - Alice (tag: v2.0) -|\ -| * b303e19 - (9 minutes ago) Prepare release v2.0 - Alice (feature/release_v2.0_prep) -|/ -* c6de55a - (14 minutes ago) Merge branch 'feature/feature_42' - Alice -|\ -| * 7850c00 - (14 minutes ago) Work on feature_42 - Alice (feature/feature_42) -|/ -* 0d54d68 - (19 minutes ago) Merge branch 'bugfix/bug_13' - Bob -``` diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..b682d14d5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2237 @@ +{ + "name": "quasar", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "quasar", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@cosmjs/cosmwasm-stargate": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/proto-signing": "^0.32.4", + "@cosmjs/stargate": "^0.32.4", + "chain-registry": "^1.63.79", + "cosmjs-types": "^0.9.0", + "cosmjs-utils": "^0.1.0", + "cosmwasm": "^1.1.1", + "osmojs": "^16.14.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.25.6.tgz", + "integrity": "sha512-VBj9MYyDb9tuLq7yzqjgzt6Q+IBQLrGZfdjOekyEirZPHxXWoTSGUTMrpsfi58Up73d13NfYLv8HT9vmznjzhQ==", + "license": "MIT", + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@chain-registry/types": { + "version": "0.45.62", + "resolved": "https://registry.npmjs.org/@chain-registry/types/-/types-0.45.62.tgz", + "integrity": "sha512-q7AGNgNGKF+hXb/ED67g3jypm+k7nTLVnQ1nEsdq64LeWMfJA9rmkI3a1PAhZq2rx7PBMM2UWKS2BsX+DI+syg==", + "license": "SEE LICENSE IN LICENSE" + }, + "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==", + "license": "Apache-2.0", + "dependencies": { + "@noble/hashes": "^1.0.0", + "protobufjs": "^6.8.8" + } + }, + "node_modules/@cosmjs/amino": { + "version": "0.32.3", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.32.3.tgz", + "integrity": "sha512-G4zXl+dJbqrz1sSJ56H/25l5NJEk/pAPIr8piAHgbXYw88OdAOlpA26PQvk2IbSN/rRgVbvlLTNgX2tzz1dyUA==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.32.3", + "@cosmjs/encoding": "^0.32.3", + "@cosmjs/math": "^0.32.3", + "@cosmjs/utils": "^0.32.3" + } + }, + "node_modules/@cosmjs/cli": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/cli/-/cli-0.28.13.tgz", + "integrity": "sha512-6mbtKmaamKYgaXblSyLCsyEUJTa0GpZLt+ODfwdEUpEdx/Ebwqt09yuCmk0kOQ/TqmruX8aN/ty1py3Opxa/FQ==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "0.28.13", + "@cosmjs/cosmwasm-stargate": "0.28.13", + "@cosmjs/crypto": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/faucet-client": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/proto-signing": "0.28.13", + "@cosmjs/stargate": "0.28.13", + "@cosmjs/tendermint-rpc": "0.28.13", + "@cosmjs/utils": "0.28.13", + "axios": "^0.21.2", + "babylon": "^6.18.0", + "chalk": "^4", + "cosmjs-types": "^0.4.0", + "diff": "^4", + "recast": "^0.20", + "ts-node": "^8", + "typescript": "~4.4", + "yargs": "^15.3.1" + }, + "bin": { + "cosmjs-cli": "bin/cosmjs-cli" + } + }, + "node_modules/@cosmjs/cli/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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/utils": "0.28.13" + } + }, + "node_modules/@cosmjs/cli/node_modules/@cosmjs/cosmwasm-stargate": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.28.13.tgz", + "integrity": "sha512-dVZNOiRd8btQreRUabncGhVXGCS2wToXqxi9l3KEHwCJQ2RWTshuqV+EZAdCaYHE5W6823s2Ol2W/ukA9AXJPw==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "0.28.13", + "@cosmjs/crypto": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/proto-signing": "0.28.13", + "@cosmjs/stargate": "0.28.13", + "@cosmjs/tendermint-rpc": "0.28.13", + "@cosmjs/utils": "0.28.13", + "cosmjs-types": "^0.4.0", + "long": "^4.0.0", + "pako": "^2.0.2" + } + }, + "node_modules/@cosmjs/cli/node_modules/@cosmjs/crypto": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.28.13.tgz", + "integrity": "sha512-ynKfM0q/tMBQMHJby6ad8lR3gkgBKaelQhIsCZTjClsnuC7oYT9y3ThSZCUWr7Pa9h0J8ahU2YV2oFWFVWJQzQ==", + "license": "Apache-2.0", + "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/@cosmjs/cli/node_modules/@cosmjs/encoding": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.28.13.tgz", + "integrity": "sha512-jtXbAYtV77rLHxoIrjGFsvgGjeTKttuHRv6cvuy3toCZzY7JzTclKH5O2g36IIE4lXwD9xwuhGJ2aa6A3dhNkA==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@cosmjs/cli/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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "0.28.13", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/cli/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==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@cosmjs/cli/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==", + "license": "Apache-2.0", + "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/@cosmjs/cli/node_modules/@cosmjs/socket": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.28.13.tgz", + "integrity": "sha512-lavwGxQ5VdeltyhpFtwCRVfxeWjH5D5mmN7jgx9nuCf3XSFbTcOYxrk2pQ4usenu1Q1KZdL4Yl5RCNrJuHD9Ug==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "0.28.13", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/cli/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==", + "license": "Apache-2.0", + "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/@cosmjs/cli/node_modules/@cosmjs/stream": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.28.13.tgz", + "integrity": "sha512-AnjtfwT8NwPPkd3lhZhjOlOzT0Kn9bgEu2IPOZjQ1nmG2bplsr6TJmnwn0dJxHT7UGtex17h6whKB5N4wU37Wg==", + "license": "Apache-2.0", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/cli/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==", + "license": "Apache-2.0", + "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/@cosmjs/cli/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==", + "license": "Apache-2.0" + }, + "node_modules/@cosmjs/cli/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/@cosmjs/cli/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==", + "license": "Apache-2.0", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "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==", + "license": "Apache-2.0", + "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/cosmwasm-stargate/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==", + "license": "Apache-2.0", + "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/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==", + "license": "Apache-2.0", + "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/crypto": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.32.4.tgz", + "integrity": "sha512-zicjGU051LF1V9v7bp8p7ovq+VyC91xlaHdsFOTo2oVry3KQikp8L/81RkXmUIT8FxMwdx1T7DmFwVQikcSDIw==", + "license": "Apache-2.0", + "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==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@cosmjs/faucet-client": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/faucet-client/-/faucet-client-0.28.13.tgz", + "integrity": "sha512-M6f0Wbw3hvdfYbVpfGDXwjbRAcCgMRm5slWK6cU8BpotckLvBb0xoBvrhklG/ooz6ZTZfAc2e/EJ8GVhksdvpA==", + "license": "Apache-2.0", + "dependencies": { + "axios": "^0.21.2" + } + }, + "node_modules/@cosmjs/faucet-client/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "^0.32.4", + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/ledger-amino": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/ledger-amino/-/ledger-amino-0.28.13.tgz", + "integrity": "sha512-KSwYjIFu/KXarvxxEyq3lpcJl5VvV0gAbY+tebeOvuCGHy9Px7CDOLOEHsR3ykJjYWh0hGrYwYmVk9zVHd474A==", + "license": "Apache-2.0", + "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", + "ledger-cosmos-js": "^2.1.8", + "semver": "^7.3.2" + } + }, + "node_modules/@cosmjs/ledger-amino/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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/utils": "0.28.13" + } + }, + "node_modules/@cosmjs/ledger-amino/node_modules/@cosmjs/crypto": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.28.13.tgz", + "integrity": "sha512-ynKfM0q/tMBQMHJby6ad8lR3gkgBKaelQhIsCZTjClsnuC7oYT9y3ThSZCUWr7Pa9h0J8ahU2YV2oFWFVWJQzQ==", + "license": "Apache-2.0", + "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/@cosmjs/ledger-amino/node_modules/@cosmjs/encoding": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.28.13.tgz", + "integrity": "sha512-jtXbAYtV77rLHxoIrjGFsvgGjeTKttuHRv6cvuy3toCZzY7JzTclKH5O2g36IIE4lXwD9xwuhGJ2aa6A3dhNkA==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/@cosmjs/ledger-amino/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==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/@cosmjs/ledger-amino/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==", + "license": "Apache-2.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==", + "license": "Apache-2.0", + "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==", + "license": "Apache-2.0", + "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/proto-signing/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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/utils": "^0.32.4" + } + }, + "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==", + "license": "Apache-2.0", + "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==", + "license": "Apache-2.0", + "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/stargate/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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/math": "^0.32.4", + "@cosmjs/utils": "^0.32.4" + } + }, + "node_modules/@cosmjs/stargate/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==", + "license": "Apache-2.0", + "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/stream": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.32.4.tgz", + "integrity": "sha512-Gih++NYHEiP+oyD4jNEUxU9antoC0pFSg+33Hpp0JlHwH0wXhtD3OOKnzSfDB7OIoEbrzLJUpEjOgpCp5Z+W3A==", + "license": "Apache-2.0", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/@cosmjs/tendermint-rpc": { + "version": "0.32.3", + "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.32.3.tgz", + "integrity": "sha512-xeprW+VR9xKGstqZg0H/KBZoUp8/FfFyS9ljIUTLM/UINjP2MhiwncANPS2KScfJVepGufUKk0/phHUeIBSEkw==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.32.3", + "@cosmjs/encoding": "^0.32.3", + "@cosmjs/json-rpc": "^0.32.3", + "@cosmjs/math": "^0.32.3", + "@cosmjs/socket": "^0.32.3", + "@cosmjs/stream": "^0.32.3", + "@cosmjs/utils": "^0.32.3", + "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==", + "license": "Apache-2.0" + }, + "node_modules/@cosmology/lcd": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/@cosmology/lcd/-/lcd-0.13.4.tgz", + "integrity": "sha512-llClHHHjOCie9PxnXUOxvMcWi0aVjmzkRXM6IBBXluOczRFFog23rPPfrWZPeT30dIX1SGklp0Fek28O76BkvQ==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "axios": "1.6.0" + } + }, + "node_modules/@cosmology/lcd/node_modules/axios": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.0.tgz", + "integrity": "sha512-EZ1DYihju9pwVB+jg67ogm+Tmqc6JmhamRN6I4Zt8DfZu5lbcQGw3ozH9lFejSJgs/ibaef3A9PMXPLeefFGJg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/@ledgerhq/devices": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/devices/-/devices-5.51.1.tgz", + "integrity": "sha512-4w+P0VkbjzEXC7kv8T1GJ/9AVaP9I6uasMZ/JcdwZBS3qwvKo5A5z9uGhP5c7TvItzcmPb44b5Mw2kT+WjUuAA==", + "license": "Apache-2.0", + "dependencies": { + "@ledgerhq/errors": "^5.50.0", + "@ledgerhq/logs": "^5.50.0", + "rxjs": "6", + "semver": "^7.3.5" + } + }, + "node_modules/@ledgerhq/errors": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/errors/-/errors-5.50.0.tgz", + "integrity": "sha512-gu6aJ/BHuRlpU7kgVpy2vcYk6atjB4iauP2ymF7Gk0ez0Y/6VSMVSJvubeEQN+IV60+OBK0JgeIZG7OiHaw8ow==", + "license": "Apache-2.0" + }, + "node_modules/@ledgerhq/hw-transport": { + "version": "5.51.1", + "resolved": "https://registry.npmjs.org/@ledgerhq/hw-transport/-/hw-transport-5.51.1.tgz", + "integrity": "sha512-6wDYdbWrw9VwHIcoDnqWBaDFyviyjZWv6H9vz9Vyhe4Qd7TIFmbTl/eWs6hZvtZBza9K8y7zD8ChHwRI4s9tSw==", + "license": "Apache-2.0", + "dependencies": { + "@ledgerhq/devices": "^5.51.1", + "@ledgerhq/errors": "^5.50.0", + "events": "^3.3.0" + } + }, + "node_modules/@ledgerhq/logs": { + "version": "5.50.0", + "resolved": "https://registry.npmjs.org/@ledgerhq/logs/-/logs-5.50.0.tgz", + "integrity": "sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA==", + "license": "Apache-2.0" + }, + "node_modules/@noble/hashes": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", + "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" + } + }, + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" + }, + "node_modules/@types/long": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz", + "integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "license": "MIT" + }, + "node_modules/ast-types": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", + "integrity": "sha512-O0yuUDnZeQDL+ncNGlJ78BiO4jnYI3bvMsD5prT0/nsgijG/LpNBIr63gTjVTNsiGkgQhiyCShTgxt8oXOrklA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "license": "MIT", + "bin": { + "babylon": "bin/babylon.js" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bech32": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "license": "MIT" + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chain-registry": { + "version": "1.63.79", + "resolved": "https://registry.npmjs.org/chain-registry/-/chain-registry-1.63.79.tgz", + "integrity": "sha512-3fXMRyTqJHtrqTsH7mC9WpurJFFBhO1p+lPo5zNM5gFE0BgrymsQBZcYjbX1ZEfQOpYfU49LbZkXVwGPZwhTZA==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@chain-registry/types": "^0.45.62" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "license": "Apache-2.0" + }, + "node_modules/cosmjs-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/cosmjs-utils/-/cosmjs-utils-0.1.0.tgz", + "integrity": "sha512-Ao2YhVXN+FqvbKqNeVN6I4njzRsCe3LVuPiLerMrAr6xr4MMABzvZbnY13AK/CYPrFJFJpmBCssocthAxOi59g==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@cosmjs/amino": "0.29.0", + "@cosmjs/crypto": "0.29.0", + "@cosmjs/proto-signing": "0.29.0", + "@cosmjs/stargate": "0.29.0", + "cosmjs-types": "0.5.1" + } + }, + "node_modules/cosmjs-utils/node_modules/@cosmjs/amino": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.29.0.tgz", + "integrity": "sha512-/ZUVx6nRN5YE36H3SDq9+i8g2nZ8DJQnN9fVRC8rSHQKauNkoEuK4NxTNcQ2o2EBLUT0kyYAFY2550HVsPMrgw==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "^0.29.0", + "@cosmjs/encoding": "^0.29.0", + "@cosmjs/math": "^0.29.0", + "@cosmjs/utils": "^0.29.0" + } + }, + "node_modules/cosmjs-utils/node_modules/@cosmjs/crypto": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.29.0.tgz", + "integrity": "sha512-MPJoebRGh7AcZgbfR25ci7iV+XzJiKwVq4wL8n6M5P2QdrIv7DqqniyFXcBbn9dQjMLMHnOSgT9LRv+VXzUVCA==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/encoding": "^0.29.0", + "@cosmjs/math": "^0.29.0", + "@cosmjs/utils": "^0.29.0", + "@noble/hashes": "^1", + "bn.js": "^5.2.0", + "elliptic": "^6.5.3", + "libsodium-wrappers": "^0.7.6" + } + }, + "node_modules/cosmjs-utils/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==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/cosmjs-utils/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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "^0.29.5", + "xstream": "^11.14.0" + } + }, + "node_modules/cosmjs-utils/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==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/cosmjs-utils/node_modules/@cosmjs/proto-signing": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.29.0.tgz", + "integrity": "sha512-zAdgDz5vRGAfJ5yyKYuTL7qg5UNUT7v4iV1/ZP8ZQn2fLh9QVxViAIovF4r/Y3EEI4JS5uYj/f8UeHMHQSu8hw==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "^0.29.0", + "@cosmjs/crypto": "^0.29.0", + "@cosmjs/encoding": "^0.29.0", + "@cosmjs/math": "^0.29.0", + "@cosmjs/utils": "^0.29.0", + "cosmjs-types": "^0.5.0", + "long": "^4.0.0" + } + }, + "node_modules/cosmjs-utils/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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "^0.29.5", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/cosmjs-utils/node_modules/@cosmjs/stargate": { + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.29.0.tgz", + "integrity": "sha512-BsV3iA3vMclMm/B1LYO0djBYCALr/UIvL6u9HGvM7QvpdtpQiAvskuS4PieVO/gtF9iCCBJLPqa0scwFIgvDyg==", + "license": "Apache-2.0", + "dependencies": { + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "^0.29.0", + "@cosmjs/encoding": "^0.29.0", + "@cosmjs/math": "^0.29.0", + "@cosmjs/proto-signing": "^0.29.0", + "@cosmjs/stream": "^0.29.0", + "@cosmjs/tendermint-rpc": "^0.29.0", + "@cosmjs/utils": "^0.29.0", + "cosmjs-types": "^0.5.0", + "long": "^4.0.0", + "protobufjs": "~6.11.3", + "xstream": "^11.14.0" + } + }, + "node_modules/cosmjs-utils/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==", + "license": "Apache-2.0", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/cosmjs-utils/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==", + "license": "Apache-2.0", + "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/cosmjs-utils/node_modules/@cosmjs/tendermint-rpc/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==", + "license": "Apache-2.0", + "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/cosmjs-utils/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==", + "license": "Apache-2.0" + }, + "node_modules/cosmjs-utils/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/cosmjs-utils/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==", + "license": "Apache-2.0", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/cosmwasm": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cosmwasm/-/cosmwasm-1.1.1.tgz", + "integrity": "sha512-tjpjwnRIQ6VEcTVB0Pq8+F+Xp6jdnC3BcXmcDHCJHIc5Gg4Mm++AA+6fTfR0yuiPbEAk6wYkokfLtv12I0sPNQ==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "^0.28.3", + "@cosmjs/cli": "^0.28.3", + "@cosmjs/cosmwasm-stargate": "^0.28.3", + "@cosmjs/crypto": "^0.28.3", + "@cosmjs/encoding": "^0.28.3", + "@cosmjs/faucet-client": "^0.28.3", + "@cosmjs/ledger-amino": "^0.28.3", + "@cosmjs/math": "^0.28.3", + "@cosmjs/proto-signing": "^0.28.3", + "@cosmjs/stargate": "^0.28.3", + "@cosmjs/utils": "^0.28.3" + }, + "bin": { + "cosmwasm": "src/cli/bin/cli" + } + }, + "node_modules/cosmwasm/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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/crypto": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/utils": "0.28.13" + } + }, + "node_modules/cosmwasm/node_modules/@cosmjs/cosmwasm-stargate": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/cosmwasm-stargate/-/cosmwasm-stargate-0.28.13.tgz", + "integrity": "sha512-dVZNOiRd8btQreRUabncGhVXGCS2wToXqxi9l3KEHwCJQ2RWTshuqV+EZAdCaYHE5W6823s2Ol2W/ukA9AXJPw==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "0.28.13", + "@cosmjs/crypto": "0.28.13", + "@cosmjs/encoding": "0.28.13", + "@cosmjs/math": "0.28.13", + "@cosmjs/proto-signing": "0.28.13", + "@cosmjs/stargate": "0.28.13", + "@cosmjs/tendermint-rpc": "0.28.13", + "@cosmjs/utils": "0.28.13", + "cosmjs-types": "^0.4.0", + "long": "^4.0.0", + "pako": "^2.0.2" + } + }, + "node_modules/cosmwasm/node_modules/@cosmjs/crypto": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.28.13.tgz", + "integrity": "sha512-ynKfM0q/tMBQMHJby6ad8lR3gkgBKaelQhIsCZTjClsnuC7oYT9y3ThSZCUWr7Pa9h0J8ahU2YV2oFWFVWJQzQ==", + "license": "Apache-2.0", + "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/cosmwasm/node_modules/@cosmjs/encoding": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.28.13.tgz", + "integrity": "sha512-jtXbAYtV77rLHxoIrjGFsvgGjeTKttuHRv6cvuy3toCZzY7JzTclKH5O2g36IIE4lXwD9xwuhGJ2aa6A3dhNkA==", + "license": "Apache-2.0", + "dependencies": { + "base64-js": "^1.3.0", + "bech32": "^1.1.4", + "readonly-date": "^1.0.0" + } + }, + "node_modules/cosmwasm/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==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "0.28.13", + "xstream": "^11.14.0" + } + }, + "node_modules/cosmwasm/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==", + "license": "Apache-2.0", + "dependencies": { + "bn.js": "^5.2.0" + } + }, + "node_modules/cosmwasm/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==", + "license": "Apache-2.0", + "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/cosmwasm/node_modules/@cosmjs/socket": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.28.13.tgz", + "integrity": "sha512-lavwGxQ5VdeltyhpFtwCRVfxeWjH5D5mmN7jgx9nuCf3XSFbTcOYxrk2pQ4usenu1Q1KZdL4Yl5RCNrJuHD9Ug==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/stream": "0.28.13", + "isomorphic-ws": "^4.0.1", + "ws": "^7", + "xstream": "^11.14.0" + } + }, + "node_modules/cosmwasm/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==", + "license": "Apache-2.0", + "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/cosmwasm/node_modules/@cosmjs/stream": { + "version": "0.28.13", + "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.28.13.tgz", + "integrity": "sha512-AnjtfwT8NwPPkd3lhZhjOlOzT0Kn9bgEu2IPOZjQ1nmG2bplsr6TJmnwn0dJxHT7UGtex17h6whKB5N4wU37Wg==", + "license": "Apache-2.0", + "dependencies": { + "xstream": "^11.14.0" + } + }, + "node_modules/cosmwasm/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==", + "license": "Apache-2.0", + "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/cosmwasm/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==", + "license": "Apache-2.0" + }, + "node_modules/cosmwasm/node_modules/axios": { + "version": "0.21.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", + "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/cosmwasm/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==", + "license": "Apache-2.0", + "dependencies": { + "long": "^4.0.0", + "protobufjs": "~6.11.2" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "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==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/elliptic": { + "version": "6.5.7", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz", + "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==", + "license": "MIT", + "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.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "license": "MIT", + "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", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", + "license": "MIT", + "peerDependencies": { + "ws": "*" + } + }, + "node_modules/ledger-cosmos-js": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/ledger-cosmos-js/-/ledger-cosmos-js-2.1.8.tgz", + "integrity": "sha512-Gl7SWMq+3R9OTkF1hLlg5+1geGOmcHX9OdS+INDsGNxSiKRWlsWCvQipGoDnRIQ6CPo2i/Ze58Dw0Mt/l3UYyA==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@ledgerhq/hw-transport": "^5.25.0", + "bech32": "^1.1.4", + "ripemd160": "^2.0.2" + } + }, + "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==", + "license": "ISC" + }, + "node_modules/libsodium-sumo": { + "version": "0.7.15", + "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.15.tgz", + "integrity": "sha512-5tPmqPmq8T8Nikpm1Nqj0hBHvsLFCXvdhBFV7SGOitQPZAA6jso8XoL0r4L7vmfKXr486fiQInvErHtEvizFMw==", + "license": "ISC" + }, + "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==", + "license": "ISC", + "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==", + "license": "ISC", + "dependencies": { + "libsodium-sumo": "^0.7.15" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "license": "ISC" + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "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==", + "license": "ISC" + }, + "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==", + "license": "MIT" + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/osmojs": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/osmojs/-/osmojs-16.14.0.tgz", + "integrity": "sha512-m4A5X0ZYanQ/u4/Xlz6nU9QqZEQbAKSD8SAKaDR/mIQYB6g3JkzWLgQgLMzMxDNJZKFTJCjWxHBp7al502x2aw==", + "license": "SEE LICENSE IN LICENSE", + "dependencies": { + "@cosmjs/amino": "0.32.3", + "@cosmjs/proto-signing": "0.32.3", + "@cosmjs/stargate": "0.32.3", + "@cosmjs/tendermint-rpc": "0.32.3", + "@cosmology/lcd": "^0.13.3" + } + }, + "node_modules/osmojs/node_modules/@cosmjs/proto-signing": { + "version": "0.32.3", + "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.32.3.tgz", + "integrity": "sha512-kSZ0ZUY0DwcRT0NcIn2HkadH4NKlwjfZgbLj1ABwh/4l0RgeT84QCscZCu63tJYq3K6auwqTiZSZERwlO4/nbg==", + "license": "Apache-2.0", + "dependencies": { + "@cosmjs/amino": "^0.32.3", + "@cosmjs/crypto": "^0.32.3", + "@cosmjs/encoding": "^0.32.3", + "@cosmjs/math": "^0.32.3", + "@cosmjs/utils": "^0.32.3", + "cosmjs-types": "^0.9.0" + } + }, + "node_modules/osmojs/node_modules/@cosmjs/stargate": { + "version": "0.32.3", + "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.32.3.tgz", + "integrity": "sha512-OQWzO9YWKerUinPIxrO1MARbe84XkeXJAW0lyMIjXIEikajuXZ+PwftiKA5yA+8OyditVmHVLtPud6Pjna2s5w==", + "license": "Apache-2.0", + "dependencies": { + "@confio/ics23": "^0.6.8", + "@cosmjs/amino": "^0.32.3", + "@cosmjs/encoding": "^0.32.3", + "@cosmjs/math": "^0.32.3", + "@cosmjs/proto-signing": "^0.32.3", + "@cosmjs/stream": "^0.32.3", + "@cosmjs/tendermint-rpc": "^0.32.3", + "@cosmjs/utils": "^0.32.3", + "cosmjs-types": "^0.9.0", + "xstream": "^11.14.0" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pako": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/protobufjs": { + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.4.tgz", + "integrity": "sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "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/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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==", + "license": "Apache-2.0" + }, + "node_modules/recast": { + "version": "0.20.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", + "integrity": "sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==", + "license": "MIT", + "dependencies": { + "ast-types": "0.14.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/rxjs/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/ts-node": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "license": "MIT", + "dependencies": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "typescript": ">=2.7" + } + }, + "node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, + "node_modules/typescript": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "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==", + "license": "MIT", + "dependencies": { + "globalthis": "^1.0.1", + "symbol-observable": "^2.0.3" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..20d323993 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "type": "module", + "name": "quasar", + "version": "1.0.0", + "description": "#### Chain: ![](https://github.com/quasar-finance/quasar/actions/workflows/build_go.yml/badge.svg) ![](https://github.com/quasar-finance/quasar/actions/workflows/lint_go.yml/badge.svg) ![](https://github.com/quasar-finance/quasar/actions/workflows/test_go.yml/badge.svg)", + "main": "index.js", + "directories": { + "doc": "docs", + "test": "tests" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@cosmjs/cosmwasm-stargate": "^0.32.4", + "@cosmjs/encoding": "^0.32.4", + "@cosmjs/proto-signing": "^0.32.4", + "@cosmjs/stargate": "^0.32.4", + "chain-registry": "^1.63.79", + "cosmjs-types": "^0.9.0", + "cosmjs-utils": "^0.1.0", + "cosmwasm": "^1.1.1", + "osmojs": "^16.14.0" + } +} diff --git a/scripts/generate_signed_upload_tx.sh b/scripts/generate_signed_upload_tx.sh new file mode 100644 index 000000000..97fb6c660 --- /dev/null +++ b/scripts/generate_signed_upload_tx.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -e + +if [ "$#" -ne 3 ]; then + echo "Usage: bash generate_signed_upload_tx.sh " + echo "DEPLOYER and MULTISIG refer to the names of keys that are registered with osmosisd" + exit 1 +fi + +WASM_FILE=$1 +DEPLOYER=$2 +MULTISIG=$3 + +FEES=1000000uosmo +NODE=https://rpc.osmosis.zone:443 +MULTISIG_ADDRESS=$(osmosisd keys show ${MULTISIG} | grep address | sed "s/- address: //g") +CHAIN=osmosis-1 + +osmosisd tx wasm store ${WASM_FILE} --from ${MULTISIG} --gas 25000000 --fees ${FEES} --chain-id ${CHAIN} --node ${NODE} --generate-only > tx.json +osmosisd tx sign tx.json --multisig=${MULTISIG_ADDRESS} --sign-mode amino-json --chain-id ${CHAIN} --node ${NODE} --from ${DEPLOYER} --output-document ${DEPLOYER}-signed-tx.json \ No newline at end of file diff --git a/scripts/propose_cl_vault_migration.js b/scripts/propose_cl_vault_migration.js new file mode 100644 index 000000000..c75ee7c33 --- /dev/null +++ b/scripts/propose_cl_vault_migration.js @@ -0,0 +1,30 @@ +import { createMigrateMsg, createProposalMsg, getClient, readFileAsJSON, CONTRACTS, DAODAO } from './util/osmosis.js'; + +async function main() { + const mnemonic = process.env.MNEMONIC; + const client = await getClient(mnemonic); + + const migrate_msg = { + // MIGRATION MSG ARGS + }; + let contracts = readFileAsJSON(CONTRACTS); + const newCodeId = -1 // CHANGE CODE ID; + if (newCodeId == -1) { + throw new Error('Wrong code id!'); + } + var msgs = []; + for (var contract of contracts) { + console.log(contract.name); + const msg = createMigrateMsg(contract.address, newCodeId, migrate_msg); + msgs.push(msg); + } + const title = ""; + const description = ""; + const proposalMsg = createProposalMsg(title, description, msgs); + console.log(proposalMsg.propose); + + const response = await client.execute(sender, DAODAO, proposalMsg, "auto", "", []); + console.log(response); +} + +main(); diff --git a/scripts/update_contracts_list.js b/scripts/update_contracts_list.js new file mode 100644 index 000000000..f1f18bf1b --- /dev/null +++ b/scripts/update_contracts_list.js @@ -0,0 +1,18 @@ +import { CONTRACTS, readFileAsJSON, writeFileFromJSON } from './util/osmosis.js'; + +async function main() { + const version = "0.3.1"; + const last_update = "X/Y/2024"; + let contracts = readFileAsJSON(CONTRACTS); + for (var contract of contracts) { + console.log(contract.name); + if (contract.version == version) { + continue; + } + contract.version = version; + contract.last_update = last_update; + } + writeFileFromJSON(CONTRACTS, contracts); +} + +main(); diff --git a/scripts/upload_through_multisig.sh b/scripts/upload_through_multisig.sh new file mode 100644 index 000000000..683ac7dfb --- /dev/null +++ b/scripts/upload_through_multisig.sh @@ -0,0 +1,18 @@ +#!/bin/bash + +set -e + +if [ "$#" -ne 2 ]; then + echo "Too many arguments. Please provide a string containing the names of the json files of the signed transactions." + echo "Usage: bash upload_through_multisig.sh \" \"" + exit 1 +fi + +MULTISIG=$1 +SIGNED_TXS=$2 +NODE=https://rpc.osmosis.zone:443 +CHAIN=osmosis-1 + +osmosisd tx multisign tx.json ${MULTISIG} ${SIGNED_TXS} --chain-id ${CHAIN} --node ${NODE} --from ${MULTISIG} --output-document tx_ms.json +osmosisd tx broadcast tx_ms.json --chain-id ${CHAIN} --node ${NODE} +rm tx_ms.json \ No newline at end of file diff --git a/scripts/util/osmosis.js b/scripts/util/osmosis.js new file mode 100644 index 000000000..ee2bc06cc --- /dev/null +++ b/scripts/util/osmosis.js @@ -0,0 +1,101 @@ +import { SigningCosmWasmClient } from "@cosmjs/cosmwasm-stargate"; +import { Registry } from "@cosmjs/proto-signing"; +import { AminoTypes, GasPrice } from "@cosmjs/stargate"; +import { chains } from 'chain-registry'; +import { getOfflineSignerAmino as getOfflineSigner } from 'cosmjs-utils'; +import { + cosmosAminoConverters, + cosmosProtoRegistry, + cosmwasmAminoConverters, + cosmwasmProtoRegistry, + ibcAminoConverters, + ibcProtoRegistry, + osmosisAminoConverters, + osmosisProtoRegistry +} from 'osmojs'; +import fs from 'node:fs'; + +export const RPC_ENDPOINT = "https://rpc.osmosis.zone"; +export const DAODAO = "osmo1kylkpkx7zy40429zcs5yq6hm2mlw07u872fsqud26ylyc5urpxfsvw98vn"; +export const CONTRACTS = "./smart-contracts/contracts.json"; + +export function readFileAsJSON(file) { + try { + const data = fs.readFileSync(file, 'utf8'); + return JSON.parse(data); + } catch (err) { + console.error(err); + } +} + +export function writeFileFromJSON(file, json) { + try { + fs.writeFileSync(file, JSON.stringify(json)); + } catch (err) { + console.error(err); + } +} + +export function createMigrateMsg(contract, newCodeId, migrate_msg) { + const binary_msg = Buffer.from(JSON.stringify(migrate_msg)).toString('base64'); + return { + wasm: { + migrate: { + contract_addr: contract, + msg: binary_msg, + new_code_id: newCodeId + } + } + } +} + +export function createProposalMsg(title, description, msgs) { + return { + propose: { + msg: { + propose: { + description, + msgs, + title, + } + } + } + } +} + +export async function getClient(mnemonic) { + const chain = chains.find(({ chain_id }) => chain_id === "osmosis-1"); + const signer = await getOfflineSigner({ + mnemonic, + chain + }); + const gasPrice = GasPrice.fromString("0.125uosmo"); + + const accounts = await signer.getAccounts(); + const sender = accounts[0].address; + + const protoRegistry = [ + ...cosmosProtoRegistry, + ...cosmwasmProtoRegistry, + ...ibcProtoRegistry, + ...osmosisProtoRegistry + ]; + + const aminoConverters = { + ...cosmosAminoConverters, + ...cosmwasmAminoConverters, + ...ibcAminoConverters, + ...osmosisAminoConverters + }; + + const registry = new Registry(protoRegistry); + const aminoTypes = new AminoTypes(aminoConverters); + + const client = await SigningCosmWasmClient.connectWithSigner( + RPC_ENDPOINT, + signer, + { chain, gasPrice, registry, aminoTypes } + ); + + return client; +} diff --git a/smart-contracts/contracts.json b/smart-contracts/contracts.json new file mode 100644 index 000000000..bd6eceb13 --- /dev/null +++ b/smart-contracts/contracts.json @@ -0,0 +1,122 @@ +[ + { + "name": "IST/USDC Dynamic S+", + "address": "osmo1hndc6a7pynplcujdtlqw6kd4exfxgpp50vve925tn8tv34u5k08sxukzml", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "stSAGA/SAGA Dynamic S+", + "address": "osmo1e6z70myfl9wlrnkkykluhhp6at70l9g7jma6ev7j564c5vuseh6qk8c26f", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "stkOSMO/OSMO Dynamic S+", + "address": "osmo1klzcjdcphaangl2gp9cxza9d2g50p7rarf4ktym3wles9gadqjhskzdk0s", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "milkTIA/TIA Dynamic S+", + "address": "osmo1e266z5nytx2cerslv9jw5z5c2zkrwqc7j4l625tkm8unfer6mfrqxmlggz", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "stDYDX/DYDX Dynamic S+", + "address": "osmo1j5fncvh3w4agy6sn6ndtzsdmjvk8vmchrp39v2pa7va5wk6t2cnq3nrdmm", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "OSMO/ATOM Dynamic A+", + "address": "osmo13js5psx8xcep0j9mghll3fa8xgm8krr2muaeqwvpqphcavf5krrqe8ugfp", + "version": "0.3.1", + "last_update": "09/06/2024" + }, + { + "name": "OSMO/ATOM Dynamic M+", + "address": "osmo10u2xf9ck06kx6fh4dwkhp0hc9ejyf5h4j8tds6e466ar7r8y4t3qplzxxl", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "stTIA/TIA Dynamic S+", + "address": "osmo1u4ppw4mxp00znxq5ll834dgr7ctd7jrp5hrzshch5ngfpwmp2fqsputgsx", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "OSMO/ETH Dynamic A+", + "address": "osmo1cpt2dvm78l50f4ehqdgc47twpfk8yyany09kesqd7r4xwttz89qq42gyjw", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "DYDX/USDC Dynamic A+", + "address": "osmo1cw43g597cmvwwdq4uv9l7t0y0cg9pnk8uy9806lra7znl80xmgeqfj85fj", + "version": "0.3.1", + "last_update": "09/05/2024" + }, + { + "name": "QSR/OSMO Dynamic A+", + "address": "osmo1gv5405cldsvwwrajuhlasmxxvezrs4uch4r00w6ezdqfx4jsghnq2pca62", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "YieldETH/ETH Dynamic S+", + "address": "osmo1d2lj3nquzd3vjugx8rpww95cptekzlf6vdjnl5hpmxvztjaf4tms0lae6a", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "TIA/USDC Dynamic A+", + "address": "osmo15uk8m3wchpee8gjl02lwelxlsl4uuy3pdy7u6kz7cu7krlph2xpscf53cy", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "nobleUSDC/USDT Dynamic S+", + "address": "osmo1zvyemtz9tuyhucq6vqfk556zzz62pznya6pch2ndqxtq7amlxkdq3zkl54", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "stATOM/ATOM Dynamic S+", + "address": "osmo1f080p762n24nlw0synurvf9qqyjgmhltl63u7h43acjph26lg4ks9hda9d", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "OSMO/USDC Dynamic A+", + "address": "osmo1dzp8curq2wsnht5mw3eknqw9n6990rk2n095hu3r882dxp6zcvwsxwum7q", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "OSMO/USDC Dynamic M+", + "address": "osmo1jmjnwq26f4d90t9htzagl7llfznnrglpfl0m4a94lnr3kr0fr4asgjmf8p", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "OSMO/USDT Dynamic A+", + "address": "osmo1jq30cd6vdy9x4pe09kr2dartt53mfvxtkqn7mt93m6aqa4c2vxsswuv52f", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "OSMO/USDT Dynamic M+", + "address": "osmo1jwe0hq84cvnfpfn3yvvffcxpe0wjtj3s0jtrs6xsjx6z4zca043qzhht0r", + "version": "0.3.0", + "last_update": "" + }, + { + "name": "USDC.axl/USDT Dynamic S+", + "address": "osmo1d8qurgqg0crmz7eye4jy8vm47l3a3582vzs7nlapxfqmvdag84zswcshj5", + "version": "0.3.0", + "last_update": "" + } +] \ No newline at end of file diff --git a/smart-contracts/contracts/ica/create_and_execute.sh b/smart-contracts/contracts/ica/create_and_execute.sh deleted file mode 100755 index e69de29bb..000000000 diff --git a/smart-contracts/contracts/intergamm-bindings-test/README.md b/smart-contracts/contracts/intergamm-bindings-test/README.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/smart-contracts/osmosis/contracts/cl-vault/Cargo.toml b/smart-contracts/osmosis/contracts/cl-vault/Cargo.toml index 01f3569f2..81807ffb7 100644 --- a/smart-contracts/osmosis/contracts/cl-vault/Cargo.toml +++ b/smart-contracts/osmosis/contracts/cl-vault/Cargo.toml @@ -2,7 +2,7 @@ authors = ["LaurensKubat <32776056+LaurensKubat@users.noreply.github.com>"] edition = "2021" name = "cl-vault" -version = "0.3.0" +version = "0.3.1" exclude = [ "cl_vault.wasm", @@ -45,7 +45,6 @@ cw2 = { workspace = true } num_enum = { workspace = true } apollo-cw-asset = { workspace = true } dex-router-osmosis = {workspace = true} -cw-vault-multi-standard = {git = "https://github.com/quasar-finance/cw-vault-standard", branch ="master", features = ["lockup", "force-unlock"]} osmosis-test-tube = { workspace = true, optional = true } quasar-types = { workspace = true } diff --git a/smart-contracts/osmosis/contracts/cl-vault/schema/cl-vault.json b/smart-contracts/osmosis/contracts/cl-vault/schema/cl-vault.json index d5c0df4aa..3c567fae5 100644 --- a/smart-contracts/osmosis/contracts/cl-vault/schema/cl-vault.json +++ b/smart-contracts/osmosis/contracts/cl-vault/schema/cl-vault.json @@ -1,6 +1,6 @@ { "contract_name": "cl-vault", - "contract_version": "0.3.0", + "contract_version": "0.3.1", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/smart-contracts/osmosis/contracts/cl-vault/src/contract.rs b/smart-contracts/osmosis/contracts/cl-vault/src/contract.rs index 0fea53c02..3971aec3b 100644 --- a/smart-contracts/osmosis/contracts/cl-vault/src/contract.rs +++ b/smart-contracts/osmosis/contracts/cl-vault/src/contract.rs @@ -5,7 +5,10 @@ use crate::helpers::prepend::prepend_claim_msg; use crate::instantiate::{ handle_create_denom_reply, handle_instantiate, handle_instantiate_create_position_reply, }; -use crate::msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, ModifyRangeMsg, QueryMsg}; +use crate::msg::{ + ClQueryMsg, ExecuteMsg, ExtensionExecuteMsg, ExtensionQueryMsg, InstantiateMsg, MigrateMsg, + ModifyRangeMsg, QueryMsg, +}; use crate::query::{ query_assets_from_shares, query_dex_router, query_info, query_metadata, query_pool, query_position, query_total_assets, query_total_vault_token_supply, query_user_assets, @@ -40,6 +43,7 @@ use cosmwasm_std::{ }; use cw2::set_contract_version; use cw_storage_plus::{Item, Map}; +use quasar_types::cw_vault_multi_standard::{VaultStandardExecuteMsg, VaultStandardQueryMsg}; // version info for migration info const CONTRACT_NAME: &str = "crates.io:cl-vault"; const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -63,32 +67,32 @@ pub fn execute( msg: ExecuteMsg, ) -> Result { match msg { - cw_vault_multi_standard::VaultStandardExecuteMsg::AnyDeposit { + VaultStandardExecuteMsg::AnyDeposit { recipient, max_slippage, .. // asset and amount fields are not used in this implementation, they are for CW20 tokens } => execute_any_deposit(deps, env, info, recipient, max_slippage), - cw_vault_multi_standard::VaultStandardExecuteMsg::ExactDeposit { recipient } => { + VaultStandardExecuteMsg::ExactDeposit { recipient } => { execute_exact_deposit(deps, env, info, recipient) } - cw_vault_multi_standard::VaultStandardExecuteMsg::Redeem { recipient, amount } => { + VaultStandardExecuteMsg::Redeem { recipient, amount } => { prepend_claim_msg( &env, execute_withdraw(deps, &env, info, recipient, amount.into())?, ) } - cw_vault_multi_standard::VaultStandardExecuteMsg::VaultExtension(vault_msg) => { + VaultStandardExecuteMsg::VaultExtension(vault_msg) => { match vault_msg { - crate::msg::ExtensionExecuteMsg::Admin(admin_msg) => { + ExtensionExecuteMsg::Admin(admin_msg) => { execute_admin(deps, info, admin_msg) } - crate::msg::ExtensionExecuteMsg::Merge(msg) => { + ExtensionExecuteMsg::Merge(msg) => { execute_merge_position(deps, env, info, msg) } - crate::msg::ExtensionExecuteMsg::Autocompound {} => { + ExtensionExecuteMsg::Autocompound {} => { prepend_claim_msg(&env, execute_autocompound(deps, &env, info)?) } - crate::msg::ExtensionExecuteMsg::ModifyRange(ModifyRangeMsg { + ExtensionExecuteMsg::ModifyRange(ModifyRangeMsg { lower_price, upper_price, max_slippage, @@ -111,11 +115,11 @@ pub fn execute( claim_after, )?, ), - crate::msg::ExtensionExecuteMsg::SwapNonVaultFunds { + ExtensionExecuteMsg::SwapNonVaultFunds { swap_operations, twap_window_seconds, } => execute_swap_non_vault_funds(deps, env, info, swap_operations, twap_window_seconds), - crate::msg::ExtensionExecuteMsg::CollectRewards {} => { + ExtensionExecuteMsg::CollectRewards {} => { execute_collect_rewards(deps, env) } } @@ -126,33 +130,29 @@ pub fn execute( #[cfg_attr(not(feature = "library"), entry_point)] pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result { match msg { - cw_vault_multi_standard::VaultStandardQueryMsg::VaultStandardInfo {} => todo!(), - cw_vault_multi_standard::VaultStandardQueryMsg::Info {} => { - Ok(to_json_binary(&query_info(deps)?)?) + VaultStandardQueryMsg::VaultStandardInfo {} => { + todo!() } - cw_vault_multi_standard::VaultStandardQueryMsg::PreviewDeposit { assets: _ } => todo!(), - cw_vault_multi_standard::VaultStandardQueryMsg::DepositRatio => todo!(), - cw_vault_multi_standard::VaultStandardQueryMsg::PreviewRedeem { amount: shares } => Ok( - to_json_binary(&query_assets_from_shares(deps, env, shares)?)?, - ), - cw_vault_multi_standard::VaultStandardQueryMsg::TotalAssets {} => { + VaultStandardQueryMsg::Info {} => Ok(to_json_binary(&query_info(deps)?)?), + VaultStandardQueryMsg::PreviewDeposit { assets: _ } => todo!(), + VaultStandardQueryMsg::DepositRatio => todo!(), + VaultStandardQueryMsg::PreviewRedeem { amount: shares } => Ok(to_json_binary( + &query_assets_from_shares(deps, env, shares)?, + )?), + VaultStandardQueryMsg::TotalAssets {} => { Ok(to_json_binary(&query_total_assets(deps, env)?)?) } - cw_vault_multi_standard::VaultStandardQueryMsg::TotalVaultTokenSupply {} => { + VaultStandardQueryMsg::TotalVaultTokenSupply {} => { Ok(to_json_binary(&query_total_vault_token_supply(deps)?)?) } - cw_vault_multi_standard::VaultStandardQueryMsg::ConvertToShares { amount: _ } => todo!(), - cw_vault_multi_standard::VaultStandardQueryMsg::ConvertToAssets { amount: shares } => Ok( - to_json_binary(&query_assets_from_shares(deps, env, shares)?)?, - ), - cw_vault_multi_standard::VaultStandardQueryMsg::VaultExtension(msg) => match msg { - crate::msg::ExtensionQueryMsg::Metadata {} => { - Ok(to_json_binary(&query_metadata(deps)?)?) - } - crate::msg::ExtensionQueryMsg::DexRouter {} => { - Ok(to_json_binary(&query_dex_router(deps)?)?) - } - crate::msg::ExtensionQueryMsg::Balances(msg) => match msg { + VaultStandardQueryMsg::ConvertToShares { amount: _ } => todo!(), + VaultStandardQueryMsg::ConvertToAssets { amount: shares } => Ok(to_json_binary( + &query_assets_from_shares(deps, env, shares)?, + )?), + VaultStandardQueryMsg::VaultExtension(msg) => match msg { + ExtensionQueryMsg::Metadata {} => Ok(to_json_binary(&query_metadata(deps)?)?), + ExtensionQueryMsg::DexRouter {} => Ok(to_json_binary(&query_dex_router(deps)?)?), + ExtensionQueryMsg::Balances(msg) => match msg { crate::msg::UserBalanceQueryMsg::UserSharesBalance { user } => { Ok(to_json_binary(&query_user_balance(deps, user)?)?) } @@ -160,18 +160,16 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result match msg { - crate::msg::ClQueryMsg::Pool {} => Ok(to_json_binary(&query_pool(deps)?)?), - crate::msg::ClQueryMsg::Position {} => Ok(to_json_binary(&query_position(deps)?)?), - crate::msg::ClQueryMsg::RangeAdmin {} => { + ExtensionQueryMsg::ConcentratedLiquidity(msg) => match msg { + ClQueryMsg::Pool {} => Ok(to_json_binary(&query_pool(deps)?)?), + ClQueryMsg::Position {} => Ok(to_json_binary(&query_position(deps)?)?), + ClQueryMsg::RangeAdmin {} => { let range_admin = get_range_admin(deps)?; Ok(to_json_binary(&RangeAdminResponse { address: range_admin.to_string(), })?) } - crate::msg::ClQueryMsg::VerifyTickCache => { - Ok(to_json_binary(&query_verify_tick_cache(deps)?)?) - } + ClQueryMsg::VerifyTickCache => Ok(to_json_binary(&query_verify_tick_cache(deps)?)?), }, }, } @@ -201,6 +199,8 @@ pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result Result { + let previous_version = + cw2::ensure_from_older_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?; let dex_router_item: Item = Item::new("dex_router"); dex_router_item.remove(deps.storage); // VaultConfig @@ -246,7 +246,10 @@ pub fn migrate(deps: DepsMut, _env: Env, msg: MigrateMsg) -> Result = Map::new("user_rewards"); USER_REWARDS.clear(deps.storage); - let response = Response::new().add_attribute("migrate", "successful"); + let response = Response::new() + .add_attribute("migrate", "successful") + .add_attribute("previous version", previous_version.to_string()) + .add_attribute("new version", CONTRACT_VERSION); Ok(response) } @@ -260,6 +263,7 @@ mod tests { fn test_migrate() { let env = mock_env(); let mut deps = mock_dependencies(); + assert!(set_contract_version(deps.as_mut().storage, CONTRACT_NAME, "0.3.0").is_ok()); // VaultConfig mocking #[cw_serde] @@ -272,7 +276,7 @@ mod tests { const OLD_VAULT_CONFIG: Item = Item::new("vault_config_v2"); OLD_VAULT_CONFIG .save( - &mut deps.storage, + deps.as_mut().storage, &OldVaultConfig { performance_fee: Decimal::percent(1), treasury: Addr::unchecked("treasury"), @@ -290,13 +294,17 @@ mod tests { } pub const MIGRATION_STATUS: Item = Item::new("migration_status"); MIGRATION_STATUS - .save(&mut deps.storage, &MigrationStatus::Closed) + .save(deps.as_mut().storage, &MigrationStatus::Closed) .unwrap(); // UserRewards mocking pub const USER_REWARDS: Map = Map::new("user_rewards"); USER_REWARDS - .save(&mut deps.storage, Addr::unchecked("user"), &CoinList::new()) + .save( + deps.as_mut().storage, + Addr::unchecked("user"), + &CoinList::new(), + ) .unwrap(); // Migrate and assert new states diff --git a/smart-contracts/osmosis/contracts/cl-vault/src/error.rs b/smart-contracts/osmosis/contracts/cl-vault/src/error.rs index 06d1f4395..da82edd37 100644 --- a/smart-contracts/osmosis/contracts/cl-vault/src/error.rs +++ b/smart-contracts/osmosis/contracts/cl-vault/src/error.rs @@ -4,6 +4,7 @@ use cosmwasm_std::{ CoinFromStrError, ConversionOverflowError, Decimal, Decimal256, Decimal256RangeExceeded, DecimalRangeExceeded, DivideByZeroError, OverflowError, StdError, Storage, Uint128, }; +use cw2::VersionError; use cw_utils::PaymentError; use prost::DecodeError; use quasar_types::pool_pair::PoolPairError; @@ -162,6 +163,9 @@ pub enum ContractError { #[error("{0}")] PoolPair(#[from] PoolPairError), + + #[error("{0}")] + Version(#[from] VersionError), } pub fn assert_deposits(funds: &[Coin], config: &PoolConfig) -> Result<(), ContractError> { diff --git a/smart-contracts/osmosis/contracts/cl-vault/src/msg.rs b/smart-contracts/osmosis/contracts/cl-vault/src/msg.rs index 123260d5c..8de2416d8 100644 --- a/smart-contracts/osmosis/contracts/cl-vault/src/msg.rs +++ b/smart-contracts/osmosis/contracts/cl-vault/src/msg.rs @@ -1,7 +1,7 @@ use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::{Addr, Decimal}; -use cw_vault_multi_standard::{VaultStandardExecuteMsg, VaultStandardQueryMsg}; use osmosis_std::types::osmosis::poolmanager::v1beta1::SwapAmountInRoute; +use quasar_types::cw_vault_multi_standard::{VaultStandardExecuteMsg, VaultStandardQueryMsg}; #[cfg(not(target_arch = "wasm32"))] use crate::query::{ diff --git a/smart-contracts/osmosis/contracts/cl-vault/src/query.rs b/smart-contracts/osmosis/contracts/cl-vault/src/query.rs index 9c76602cb..c04b9a9bb 100644 --- a/smart-contracts/osmosis/contracts/cl-vault/src/query.rs +++ b/smart-contracts/osmosis/contracts/cl-vault/src/query.rs @@ -8,8 +8,8 @@ use crate::vault::concentrated_liquidity::get_position; use crate::ContractError; use cosmwasm_schema::cw_serde; use cosmwasm_std::{coin, Coin, Decimal, Deps, Env, Uint128}; -use cw_vault_multi_standard::VaultInfoResponse; use osmosis_std::types::cosmos::bank::v1beta1::BankQuerier; +use quasar_types::cw_vault_multi_standard::VaultInfoResponse; #[cw_serde] pub struct MetadataResponse { diff --git a/smart-contracts/osmosis/contracts/cl-vault/tests/test-tube/autocompound.rs b/smart-contracts/osmosis/contracts/cl-vault/tests/test-tube/autocompound.rs index 02c9a2121..18a40881b 100644 --- a/smart-contracts/osmosis/contracts/cl-vault/tests/test-tube/autocompound.rs +++ b/smart-contracts/osmosis/contracts/cl-vault/tests/test-tube/autocompound.rs @@ -19,11 +19,11 @@ use cl_vault::query::{ }; use cosmwasm_std::assert_approx_eq; use cosmwasm_std::{Coin, Uint128}; -use cw_vault_multi_standard::VaultStandardQueryMsg::VaultExtension; use osmosis_std::types::cosmos::bank::v1beta1::MsgSend; use osmosis_std::types::cosmos::base::v1beta1::Coin as OsmoCoin; use osmosis_std::types::osmosis::poolmanager::v1beta1::SwapAmountInRoute; use osmosis_test_tube::{Account, Bank, Module, Wasm}; +use quasar_types::cw_vault_multi_standard::VaultStandardQueryMsg::VaultExtension; const DENOM_REWARD_AMOUNT: u128 = 100_000_000_000; const APPROX_EQ_FACTOR: &str = "0.00005"; diff --git a/smart-contracts/osmosis/contracts/cl-vault/tests/test-tube/initialize.rs b/smart-contracts/osmosis/contracts/cl-vault/tests/test-tube/initialize.rs index b38d8c988..df27536e6 100644 --- a/smart-contracts/osmosis/contracts/cl-vault/tests/test-tube/initialize.rs +++ b/smart-contracts/osmosis/contracts/cl-vault/tests/test-tube/initialize.rs @@ -9,7 +9,6 @@ use cl_vault::{ query::PoolResponse, }; use cosmwasm_std::{Coin, Decimal}; -use cw_vault_multi_standard::VaultInfoResponse; use osmosis_std::types::{ cosmos::base::v1beta1, osmosis::{ @@ -22,6 +21,7 @@ use osmosis_test_tube::{ cosmrs::proto::traits::Message, Account, ConcentratedLiquidity, Module, PoolManager, TokenFactory, Wasm, }; +use quasar_types::cw_vault_multi_standard::VaultInfoResponse; use std::str::FromStr; #[test] diff --git a/smart-contracts/osmosis/packages/quasar-types/Cargo.toml b/smart-contracts/osmosis/packages/quasar-types/Cargo.toml index 4655ef327..11054a062 100644 --- a/smart-contracts/osmosis/packages/quasar-types/Cargo.toml +++ b/smart-contracts/osmosis/packages/quasar-types/Cargo.toml @@ -4,6 +4,10 @@ name = "quasar-types" version = "0.1.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[features] +default = ["lockup", "force-unlock"] +lockup = [] +force-unlock = [] [dependencies] cosmwasm-std = { workspace = true } @@ -11,6 +15,7 @@ osmosis-std = { workspace = true } osmosis-std-derive = { workspace = true } cosmwasm-schema = { workspace = true } cw-storage-plus ={ workspace = true } +cw-utils ={ workspace = true } schemars ={ workspace = true } serde = { workspace = true } thiserror = { workspace = true } diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/cw4626.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/cw4626.rs new file mode 100644 index 000000000..374dce642 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/cw4626.rs @@ -0,0 +1,270 @@ +use crate::msg::{ + ExtensionExecuteMsg, ExtensionQueryMsg, VaultInfoResponse, VaultStandardInfoResponse, +}; +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{to_json_binary, Binary, Coin, CosmosMsg, Empty, StdResult, Uint128, WasmMsg}; +use cw20::{ + AllAccountsResponse, AllAllowancesResponse, AllowanceResponse, BalanceResponse, + DownloadLogoResponse, MarketingInfoResponse, TokenInfoResponse, +}; +use cw20::{Expiration, Logo}; +use schemars::JsonSchema; + +// TODO update for multi asset support + +/// The default ExecuteMsg variants that a vault using the Cw4626 extension must +/// implement. This includes all of the variants from the default +/// VaultStandardExecuteMsg, plus the variants from the CW20 standard. This enum +/// can be extended with additional variants by defining an extension enum and +/// then passing it as the generic argument `T` to this enum. +#[cw_serde] +pub enum Cw4626ExecuteMsg { + //-------------------------------------------------------------------------- + // Standard CW20 ExecuteMsgs + //-------------------------------------------------------------------------- + /// Transfer is a base message to move tokens to another account without + /// triggering actions + Transfer { recipient: String, amount: Uint128 }, + /// Send is a base message to transfer tokens to a contract and trigger an + /// action on the receiving contract. + Send { + contract: String, + amount: Uint128, + msg: Binary, + }, + /// Only with "approval" extension. Allows spender to access an additional + /// amount tokens from the owner's (env.sender) account. If expires is + /// Some(), overwrites current allowance expiration with this one. + IncreaseAllowance { + spender: String, + amount: Uint128, + expires: Option, + }, + /// Only with "approval" extension. Lowers the spender's access of tokens + /// from the owner's (env.sender) account by amount. If expires is Some(), + /// overwrites current allowance expiration with this one. + DecreaseAllowance { + spender: String, + amount: Uint128, + expires: Option, + }, + /// Only with "approval" extension. Transfers amount tokens from owner -> + /// recipient if `env.sender` has sufficient pre-approval. + TransferFrom { + owner: String, + recipient: String, + amount: Uint128, + }, + /// Only with "approval" extension. Sends amount tokens from owner -> + /// contract if `env.sender` has sufficient pre-approval. + SendFrom { + owner: String, + contract: String, + amount: Uint128, + msg: Binary, + }, + /// Only with the "marketing" extension. If authorized, updates marketing + /// metadata. Setting None/null for any of these will leave it + /// unchanged. Setting Some("") will clear this field on the contract + /// storage + UpdateMarketing { + /// A URL pointing to the project behind this token. + project: Option, + /// A longer description of the token and it's utility. Designed for + /// tooltips or such + description: Option, + /// The address (if any) who can update this data structure + marketing: Option, + }, + /// If set as the "marketing" role on the contract, upload a new URL, SVG, + /// or PNG for the token + UploadLogo(Logo), + + //-------------------------------------------------------------------------- + // Vault Standard ExecuteMsgs + //-------------------------------------------------------------------------- + /// Called to deposit into the vault. Native assets are passed in the funds + /// parameter. + Deposit { + /// The amount of base tokens to deposit + amount: Uint128, + /// An optional field containing the recipient of the vault token. If + /// not set, the caller address will be used instead. + recipient: Option, + }, + + /// Called to redeem vault tokens and receive assets back from the vault. + /// The native vault token must be passed in the funds parameter, unless the + /// lockup extension is called, in which case the vault token has already + /// been passed to ExecuteMsg::Unlock. + Redeem { + /// Amount of vault tokens to redeem + amount: Uint128, + /// An optional field containing which address should receive the + /// withdrawn base tokens. If not set, the caller address will + /// be used instead. + recipient: Option, + }, + + /// Called to execute functionality of any enabled extensions. + VaultExtension(T), +} + +impl Cw4626ExecuteMsg { + /// Convert a [`Cw4626ExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&self)?, + funds, + } + .into()) + } +} + +/// The default QueryMsg variants that a vault using the Cw4626 extension must +/// implement. This includes all of the variants from the default +/// VaultStandardQueryMsg, plus the variants from the CW20 standard. This enum +/// can be extended with additional variants by defining an extension enum and +/// then passing it as the generic argument `T` to this enum. +#[cw_serde] +#[derive(QueryResponses)] +pub enum Cw4626QueryMsg +where + T: JsonSchema, +{ + //-------------------------------------------------------------------------- + // Standard CW20 QueryMsgs + //-------------------------------------------------------------------------- + /// Returns the current balance of the given address, 0 if unset. + /// Return type: BalanceResponse. + #[returns(BalanceResponse)] + Balance { address: String }, + /// Returns metadata on the contract - name, decimals, supply, etc. + /// Return type: TokenInfoResponse. + #[returns(TokenInfoResponse)] + TokenInfo {}, + /// Only with "allowance" extension. + /// Returns how much spender can use from owner account, 0 if unset. + /// Return type: AllowanceResponse. + #[returns(AllowanceResponse)] + Allowance { owner: String, spender: String }, + /// Only with "marketing" extension + /// Returns more metadata on the contract to display in the client: + /// - description, logo, project url, etc. + /// Return type: MarketingInfoResponse. + #[returns(MarketingInfoResponse)] + MarketingInfo {}, + /// Only with "marketing" extension + /// Downloads the embedded logo data (if stored on chain). Errors if no logo + /// data stored for this contract. + /// Return type: DownloadLogoResponse. + #[returns(DownloadLogoResponse)] + DownloadLogo {}, + /// Only with "enumerable" extension (and "allowances") + /// Returns all allowances this owner has approved. Supports pagination. + /// Return type: AllAllowancesResponse. + #[returns(AllAllowancesResponse)] + AllAllowances { + owner: String, + start_after: Option, + limit: Option, + }, + /// Only with "enumerable" extension + /// Returns all accounts that have balances. Supports pagination. + /// Return type: AllAccountsResponse. + #[returns(AllAccountsResponse)] + AllAccounts { + start_after: Option, + limit: Option, + }, + + //-------------------------------------------------------------------------- + // Vault Standard QueryMsgs + //-------------------------------------------------------------------------- + /// Returns `VaultStandardInfoResponse` with information on the version of + /// the vault standard used as well as any enabled extensions. + #[returns(VaultStandardInfoResponse)] + VaultStandardInfo {}, + + /// Returns `VaultInfoResponse` representing vault requirements, lockup, & + /// vault token denom. + #[returns(VaultInfoResponse)] + Info {}, + + /// Returns `Uint128` amount of vault tokens that will be returned for the + /// passed in `amount` of base tokens. + /// + /// Allows an on-chain or off-chain user to simulate the effects of their + /// deposit at the current block, given current on-chain conditions. + /// + /// Must return as close to and no more than the exact amount of vault + /// tokens that would be minted in a deposit call in the same transaction. + /// I.e. Deposit should return the same or more vault tokens as + /// PreviewDeposit if called in the same transaction. + #[returns(Uint128)] + PreviewDeposit { + /// The amount of base tokens to preview depositing. + amount: Uint128, + }, + + /// Returns `Uint128` amount of base tokens that would be withdrawn in + /// exchange for redeeming `amount` of vault tokens. + /// + /// Allows an on-chain or off-chain user to simulate the effects of their + /// redeem at the current block, given current on-chain conditions. + /// + /// Must return as close to and no more than the exact amount of base tokens + /// that would be withdrawn in a redeem call in the same transaction. + #[returns(Uint128)] + PreviewRedeem { + /// The amount of vault tokens to preview redeeming. + amount: Uint128, + }, + + /// Returns the amount of assets managed by the vault denominated in base + /// tokens. Useful for display purposes, and does not have to confer the + /// exact amount of base tokens. + #[returns(Uint128)] + TotalAssets {}, + + /// Returns `Uint128` total amount of vault tokens in circulation. + #[returns(Uint128)] + TotalVaultTokenSupply {}, + + /// The amount of vault tokens that the vault would exchange for the amount + /// of assets provided, in an ideal scenario where all the conditions + /// are met. + /// + /// Useful for display purposes and does not have to confer the exact amount + /// of vault tokens returned by the vault if the passed in assets were + /// deposited. This calculation should not reflect the "per-user" + /// price-per-share, and instead should reflect the "average-user’s" + /// price-per-share, meaning what the average user should expect to see + /// when exchanging to and from. + #[returns(Uint128)] + ConvertToShares { + /// The amount of base tokens to convert to vault tokens. + amount: Uint128, + }, + + /// Returns the amount of base tokens that the Vault would exchange for + /// the `amount` of vault tokens provided, in an ideal scenario where all + /// the conditions are met. + /// + /// Useful for display purposes and does not have to confer the exact amount + /// of assets returned by the vault if the passed in vault tokens were + /// redeemed. This calculation should not reflect the "per-user" + /// price-per-share, and instead should reflect the "average-user’s" + /// price-per-share, meaning what the average user should expect to see + /// when exchanging to and from. + #[returns(Uint128)] + ConvertToAssets { + /// The amount of vault tokens to convert to base tokens. + amount: Uint128, + }, + + /// Handle queries of any enabled extensions. + #[returns(Empty)] + VaultExtension(T), +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/force_unlock.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/force_unlock.rs new file mode 100644 index 000000000..d44460f69 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/force_unlock.rs @@ -0,0 +1,57 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{to_json_binary, Coin, CosmosMsg, StdResult, Uint128, WasmMsg}; + +use crate::cw_vault_multi_standard::msg::{ExtensionExecuteMsg, VaultStandardExecuteMsg}; + +/// Additional ExecuteMsg variants for vaults that enable the ForceUnlock +/// extension. +#[cw_serde] +pub enum ForceUnlockExecuteMsg { + /// Can be called by whitelisted addresses to bypass the lockup and + /// immediately return the base tokens. Used in the event of + /// liquidation. The caller must pass the native vault tokens in the funds + /// field. + ForceRedeem { + /// The address which should receive the withdrawn assets. If not set, + /// the caller address will be used instead. + recipient: Option, + /// The amount of vault tokens to force redeem. + amount: Uint128, + }, + + /// Force withdraw from a position that is already unlocking (Unlock has + /// already been called). + ForceWithdrawUnlocking { + /// The ID of the unlocking position from which to force withdraw + lockup_id: u64, + /// Optional amount of base tokens to be force withdrawn. + /// If None is passed, the entire position will be force withdrawn. + amount: Option, + /// The address which should receive the withdrawn assets. If not set, + /// the assets will be sent to the caller. + recipient: Option, + }, + + /// Update the whitelist of addresses that can call ForceRedeem and + /// ForceWithdrawUnlocking. + UpdateForceWithdrawWhitelist { + /// Addresses to add to the whitelist. + add_addresses: Vec, + /// Addresses to remove from the whitelist. + remove_addresses: Vec, + }, +} + +impl ForceUnlockExecuteMsg { + /// Convert a [`ForceUnlockExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&VaultStandardExecuteMsg::VaultExtension( + ExtensionExecuteMsg::ForceUnlock(self), + ))?, + funds, + } + .into()) + } +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/keeper.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/keeper.rs new file mode 100644 index 000000000..6d41a6ed3 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/keeper.rs @@ -0,0 +1,77 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{to_json_binary, Addr, Coin, CosmosMsg, StdResult, WasmMsg}; + +use crate::{ExtensionExecuteMsg, VaultStandardExecuteMsg}; + +/// A job that can be performed by a keeper. +#[cw_serde] +pub struct KeeperJob { + /// The numeric ID of the job + pub id: u64, + /// whether only whitelisted keepers can execute the job or not + pub whitelist: bool, + /// A list of whitelisted addresses that can execute the job + pub whitelisted_keepers: Vec, +} + +/// Additional ExecuteMsg variants for vaults that enable the Keeper extension. +#[cw_serde] +pub enum KeeperExecuteMsg { + /// Callable by vault admin to whitelist a keeper to be able to execute a + /// job + WhitelistKeeper { + /// The ID of the job to whitelist the keeper for + job_id: u64, + /// The address of the keeper to whitelist + keeper: String, + }, + /// Callable by vault admin to remove a keeper from the whitelist of a job + BlacklistKeeper { + /// The ID of the job to blacklist the keeper for + job_id: u64, + /// The address of the keeper to blacklist + keeper: String, + }, + /// Execute a keeper job. Should only be able to be called if + /// [`KeeperQueryMsg::KeeperJobReady`] returns true, and only by whitelisted + /// keepers if the whitelist bool on the KeeperJob is set to true. + ExecuteJob { + /// The ID of the job to execute + job_id: u64, + }, +} + +impl KeeperExecuteMsg { + /// Convert a [`KeeperExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&VaultStandardExecuteMsg::VaultExtension( + ExtensionExecuteMsg::Keeper(self), + ))?, + funds, + } + .into()) + } +} + +/// Additional QueryMsg variants for vaults that enable the Keeper extension. +#[cw_serde] +#[derive(QueryResponses)] +pub enum KeeperQueryMsg { + /// Returns [`Vec`] + #[returns(Vec)] + KeeperJobs {}, + /// Returns [`Vec`] + #[returns(Vec)] + WhitelistedKeepers { + /// The ID of the job to get the whitelisted keepers for + job_id: u64, + }, + /// Returns bool, whether the keeper job can be executed or not + #[returns(bool)] + KeeperJobReady { + /// The ID of the job to check whether it is ready to be executed + job_id: u64, + }, +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/lockup.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/lockup.rs new file mode 100644 index 000000000..e2b124629 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/lockup.rs @@ -0,0 +1,108 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{to_json_binary, Addr, Coin, CosmosMsg, StdResult, Uint128, WasmMsg}; +#[cfg(not(target_arch = "wasm32"))] +use cw_utils::Duration; +use cw_utils::Expiration; + +use crate::cw_vault_multi_standard::msg::{ExtensionExecuteMsg, VaultStandardExecuteMsg}; + +/// Type for the unlocking position created event emitted on call to `Unlock`. +pub const UNLOCKING_POSITION_CREATED_EVENT_TYPE: &str = "unlocking_position_created"; +/// Key for the lockup id attribute in the "unlocking position created" event +/// that is emitted on call to `Unlock`. +pub const UNLOCKING_POSITION_ATTR_KEY: &str = "lockup_id"; + +/// Additional ExecuteMsg variants for vaults that enable the Lockup extension. +#[cw_serde] +pub enum LockupExecuteMsg { + /// Unlock is called to initiate unlocking a locked position held by the + /// vault. + /// The caller must pass the native vault tokens in the funds field. + /// Emits an event with type `UNLOCKING_POSITION_CREATED_EVENT_TYPE` with + /// an attribute with key `UNLOCKING_POSITION_ATTR_KEY` containing an u64 + /// lockup_id. + /// + /// Like Redeem, this takes an amount so that the same API can be used for + /// CW4626 and native tokens. + Unlock { + /// The amount of vault tokens to unlock. + amount: Uint128, + }, + + /// EmergencyUnlock is called to initiate unlocking a locked position held + /// by the vault. + /// This call should simply unlock `amount` of vault tokens, without performing + /// any other side effects that might cause the transaction to fail. Such + /// as for example compoundning rewards for an LP position. + EmergencyUnlock { + /// The amount of vault tokens to unlock. + amount: Uint128, + }, + + /// Withdraw an unlocking position that has finished unlocking. + WithdrawUnlocked { + /// An optional field containing which address should receive the + /// withdrawn base tokens. If not set, the caller address will be + /// used instead. + recipient: Option, + /// The ID of the expired lockup to withdraw from. + lockup_id: u64, + }, +} + +impl LockupExecuteMsg { + /// Convert a [`LockupExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&VaultStandardExecuteMsg::VaultExtension( + ExtensionExecuteMsg::Lockup(self), + ))?, + funds, + } + .into()) + } +} + +/// Additional QueryMsg variants for vaults that enable the Lockup extension. +#[cw_serde] +#[derive(QueryResponses)] +pub enum LockupQueryMsg { + /// Returns a `Vec` containing all the currently + /// unclaimed lockup positions for the `owner`. + #[returns(Vec)] + UnlockingPositions { + /// The address of the owner of the lockup + owner: String, + /// Return results only after this lockup_id + start_after: Option, + /// Max amount of results to return + limit: Option, + }, + + /// Returns an `UnlockingPosition` info about a specific lockup, by owner + /// and ID. + #[returns(UnlockingPosition)] + UnlockingPosition { + /// The ID of the lockup to query + lockup_id: u64, + }, + + /// Returns `cw_utils::Duration` duration of the lockup of the vault. + #[returns(Duration)] + LockupDuration {}, +} + +/// Info about a currenly unlocking position. +#[cw_serde] +pub struct UnlockingPosition { + /// The ID of the lockup. + pub id: u64, + /// The address of the owner of the lockup. + pub owner: Addr, + /// A `cw_utils::Expiration` containing information about when the position + /// completes unlocking. + pub release_at: Expiration, + /// The amount of base tokens that are being unlocked. + pub base_token_amount: Uint128, +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/mod.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/mod.rs new file mode 100644 index 000000000..543ee6d81 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/extensions/mod.rs @@ -0,0 +1,43 @@ +/// The lockup extension can be used to create vaults where the vault tokens are +/// not immediately reedemable. Instead of normally calling the +/// `VaultStandardExecuteMsg::Redeem` variant, the user has to call the `Unlock` +/// variant on the Lockup extension `ExecuteMsg` and wait for a specified period +/// of time before they can withdraw their base tokens via the +/// `WithdrawUnlocked` variant. +#[cfg(feature = "lockup")] +#[cfg_attr(docsrs, doc(cfg(feature = "lockup")))] +pub mod lockup; + +/// The force unlock extension can be used to create a vault that also +/// implements the `Lockup` extension, but where some whitelisted addresses are +/// allowed to call the `ForceUnlock` variant on the extension `ExecuteMsg` and +/// immediately unlock the vault tokens of the specified user. This is useful if +/// the vault is used with leverage and a liquidator needs to be able to +/// liquidate the tokens locked in the vault. +#[cfg(feature = "force-unlock")] +#[cfg_attr(docsrs, doc(cfg(feature = "force-unlock")))] +pub mod force_unlock; + +/// The keeper extension can be used to add functionality for either whitelisted +/// addresses or anyone to act as a "keeper" for the vault and call functions to +/// perform jobs that need to be done to keep the vault running. +#[cfg(feature = "keeper")] +#[cfg_attr(docsrs, doc(cfg(feature = "keeper")))] +pub mod keeper; + +/// The Cw4626 extension is the only extension provided with in this repo that +/// does not extend the standard `ExecuteMsg` and `QueryMsg` enums with by +/// putting its variants inside of a `VaultExtension` variant. Instead it adds +/// more variants at the top level, namely the variants from the [CW20 +/// standard](https://github.com/CosmWasm/cw-plus/tree/main/packages/cw20) This +/// is inspired by the [ERC-4626 standard on +/// Ethereum](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) +/// and allows the vault to, instead of using a Cosmos native token as the vault +/// token, have the vault contract be it's own vault token by also implementing +/// the CW20 standard. This is useful if you are writing a vault on a chain that +/// does not yet have the [TokenFactory +/// module](https://github.com/CosmWasm/token-factory) available and can +/// therefore not issue a Cosmos native token as the vault token. +#[cfg(feature = "cw4626")] +#[cfg_attr(docsrs, doc(cfg(feature = "cw4626")))] +pub mod cw4626; diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/mod.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/mod.rs new file mode 100644 index 000000000..319efe2c3 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/mod.rs @@ -0,0 +1,124 @@ +#![cfg_attr(docsrs, feature(doc_cfg))] +//! # CosmWasm Vault Standard +//! +//! A standard interface for tokenized vaults written in CosmWasm. This repo +//! contains a set of `ExecuteMsg` and `QueryMsg` variants that should be +//! implemented by a vault contract that adheres to this standard. +//! +//! ## Vault Standard Fundamentals +//! There are a few things to know about the vault standard: +//! * Each vault has one specific token that is used for deposits, withdrawals +//! and accounting. This token is called the `base token`. +//! * Each vault has a `vault token` that represents the users share in the +//! vault. The number of vault tokens the user receives should be based on the +//! the number of base tokens they deposit. +//! +//! ## How to create a vault contract that adheres to this standard +//! +//! To create a vault contract that adheres to the standard, all you need to do +//! is import the [VaultStandardExecuteMsg] and [VaultStandardQueryMsg] enums +//! and use them in the entrypoints of your contracts. +//! +//! The [VaultStandardExecuteMsg] and [VaultStandardQueryMsg] enums define a set +//! of variants that should be enough to cover most vault contract use cases, +//! and all vaults that adhere to the standard must implement all of the +//! provided default variants. If however your use case requires additional +//! variants, please see the section on [how to use +//! extensions](#how-to-use-extensions). +//! +//! ## Description and specification of ExecuteMsg and QueryMsg variants +//! Please refer to the documentation page for each of the enums +//! [VaultStandardExecuteMsg] and [VaultStandardQueryMsg] for a complete +//! description of each variant. +//! +//! ## How to use Extensions +//! +//! If the standard set of `ExecuteMsg` and `QueryMsg` variants are not enough +//! for your use case, you can include additional ones by defining an extension. +//! The preferred way to do this is by creating a new enum that extends the +//! exported [VaultStandardExecuteMsg] and [VaultStandardQueryMsg] enums. For +//! example: +//! +//! ```ignore +//! pub enum MyExtensionExecuteMsg { +//! MyVariant1 { ... }, +//! MyVariant2 { ... }, +//! } +//! ``` +//! This enum can then be included in an enum with all the Extensions that your +//! vault uses and then be passed in as the generic argument `T` to +//! [`VaultStandardExecuteMsg`]. For example: +//! +//! ```ignore +//! pub enum ExtensionExecuteMsg { +//! MyExtension(MyExtensionExecuteMsg), +//! Lockup(LockupExecuteMsg), +//! } +//! +//! pub type ExecuteMsg = VaultStandardExecuteMsg; +//! ``` +//! +//! Now you can use the `ExecuteMsg` enum in your contract entrypoints instead +//! of the default [VaultStandardExecuteMsg] enum. +//! +//! ## Included Extensions +//! +//! The following extensions are included in this repo: +//! * [Lockup](crate::extensions::lockup) +//! * [ForceUnlock](crate::extensions::force_unlock) +//! * [Keeper](crate::extensions::keeper) +//! * [Cw4626](crate::extensions::cw4626) +//! +//! Each of these extensions are available in this repo via cargo features. To +//! use them, you can import the crate with a feature flag like this: +//! +//! ```toml +//! cw-vault-standard = { version = "0.2.0", features = ["lockup", "force_unlock"] } +//! ``` +//! +//! A short description of each extension can be found below. +//! +//! ### Lockup +//! The lockup extension can be used to create vaults where the vault tokens are +//! not immediately reedemable. Instead of normally calling the +//! [`VaultStandardExecuteMsg::Redeem`] variant, the user has to call the +//! `Unlock` variant on the Lockup extension `ExecuteMsg` and wait for a +//! specified period of time before they can withdraw their base tokens via the +//! `WithdrawUnlocked` variant. +//! +//! ### ForceUnlock +//! The force unlock extension can be used to create a vault that also +//! implements the `Lockup` extension, but where some whitelisted addresses are +//! allowed to call the `ForceUnlock` variant on the extension `ExecuteMsg` and +//! immediately unlock the vault tokens of the specified user. This is useful if +//! the vault is used with leverage and a liquidator needs to be able to +//! liquidate the tokens locked in the vault. +//! +//! ### Keeper +//! The keeper extension can be used to add functionality for either whitelisted +//! addresses or anyone to act as a "keeper" for the vault and call functions to +//! perform jobs that need to be done to keep the vault running. +//! +//! ### Cw4626 +//! The Cw4626 extension is the only extension provided with in this repo that +//! does not extend the default [`VaultStandardExecuteMsg`] and +//! [`VaultStandardQueryMsg`] enums by putting its variants inside of the +//! [`VaultStandardExecuteMsg::VaultExtension`] variant. Instead it adds more +//! variants at the top level, namely the variants from the [CW20 +//! standard](https://github.com/CosmWasm/cw-plus/tree/main/packages/cw20). This +//! is inspired by the [ERC-4626 standard on +//! Ethereum](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) +//! and allows the vault to, instead of using a Cosmos native token as the vault +//! token, have the vault contract be it's own vault token by also implementing +//! the CW20 standard. This is useful if you are writing a vault on a chain that +//! does not yet have the [TokenFactory +//! module](https://github.com/CosmWasm/token-factory) available and can +//! therefore not issue a Cosmos native token as the vault token. + +/// Module containing some pre-defined vault standard extensions. +pub mod extensions; +/// Module containing the vault standard ExecutMsg and QueryMsg enums, as well +/// as QueryMsg response types. +pub mod msg; + +pub use msg::*; diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/msg.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/msg.rs new file mode 100644 index 000000000..f9b993568 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_multi_standard/msg.rs @@ -0,0 +1,231 @@ +#[cfg(feature = "force-unlock")] +use crate::cw_vault_multi_standard::extensions::force_unlock::ForceUnlockExecuteMsg; +#[cfg(feature = "keeper")] +use crate::cw_vault_multi_standard::extensions::keeper::{KeeperExecuteMsg, KeeperQueryMsg}; +#[cfg(feature = "lockup")] +use crate::cw_vault_multi_standard::extensions::lockup::{LockupExecuteMsg, LockupQueryMsg}; + +use cosmwasm_schema::{cw_serde, QueryResponses}; +#[cfg(not(target_arch = "wasm32"))] +use cosmwasm_std::Empty; +use cosmwasm_std::{to_json_binary, Coin, CosmosMsg, Decimal, StdResult, Uint128, WasmMsg}; +use schemars::JsonSchema; + +/// The default ExecuteMsg variants that all vaults must implement. +/// This enum can be extended with additional variants by defining an extension +/// enum and then passing it as the generic argument `T` to this enum. +#[cw_serde] +pub enum VaultStandardExecuteMsg { + /// Called to deposit an any of the assets into the vault. Assets are passed in the funds parameter. + /// This should functions as a deposit function that "just handles the deposit", it might swap user funds to + /// the ratio needed. This should support both single sided deposits aswell as unbalanced deposits + AnyDeposit { + /// The amount of tokens to deposit. + amount: Uint128, + /// the asset to deposit + asset: String, + /// The optional recipient of the vault token. If not set, the caller + /// address will be used instead. + recipient: Option, + /// The maximum slippage allowed for swap between vault assets for deposit + max_slippage: Decimal, + }, + + /// Called to deposit multiple assets into the vault. The assets should be passed in the funds + /// parameter. The vault should either accept funds in the correct ratio and error on incorrect ratio's, + /// or refund and funds that are not in the correct ratio + ExactDeposit { + /// The optional recipient of the vault token. If not set, the caller + /// address will be used instead. + recipient: Option, + }, + + /// Called to redeem vault tokens and receive assets back from the vault. + /// The native vault token must be passed in the funds parameter, unless the + /// lockup extension is called, in which case the vault token has already + /// been passed to ExecuteMsg::Unlock. + Redeem { + /// An optional field containing which address should receive the + /// withdrawn base tokens. If not set, the caller address will be + /// used instead. + recipient: Option, + /// The amount of vault tokens sent to the contract. In the case that + /// the vault token is a Cosmos native denom, we of course have this + /// information in info.funds, but if the vault implements the + /// Cw4626 API, then we need this argument. We figured it's + /// better to have one API for both types of vaults, so we + /// require this argument. + amount: Uint128, + }, + + /// Called to execute functionality of any enabled extensions. + VaultExtension(T), +} + +impl VaultStandardExecuteMsg { + /// Convert a [`VaultStandardExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&self)?, + funds, + } + .into()) + } +} + +/// Contains ExecuteMsgs of all enabled extensions. To enable extensions defined +/// outside of this crate, you can define your own `ExtensionExecuteMsg` type +/// in your contract crate and pass it in as the generic parameter to ExecuteMsg +#[cw_serde] +pub enum ExtensionExecuteMsg { + #[cfg(feature = "keeper")] + Keeper(KeeperExecuteMsg), + #[cfg(feature = "lockup")] + Lockup(LockupExecuteMsg), + #[cfg(feature = "force-unlock")] + ForceUnlock(ForceUnlockExecuteMsg), +} + +/// The default QueryMsg variants that all vaults must implement. +/// This enum can be extended with additional variants by defining an extension +/// enum and then passing it as the generic argument `T` to this enum. +#[cw_serde] +#[derive(QueryResponses)] +pub enum VaultStandardQueryMsg +where + T: JsonSchema, +{ + /// Returns `VaultStandardInfoResponse` with information on the version of + /// the vault standard used as well as any enabled extensions. + #[returns(VaultStandardInfoResponse)] + VaultStandardInfo {}, + + /// Returns `VaultInfoResponse` representing vault requirements, lockup, & + /// vault token denom. + #[returns(VaultInfoResponse)] + Info {}, + + /// Returns `Uint128` amount of vault tokens that will be returned for the + /// passed in assets. If the vault cannot accept this set tokens, + /// the query should error. This can be due to wrong ratio's, or + /// missing or superfluous assets + /// + /// Allows an on-chain or off-chain user to simulate the effects of their + /// deposit at the current block, given current on-chain conditions. + /// + /// Must return as close to and no more than the exact amount of vault + /// tokens that would be minted in a deposit call in the same transaction. + /// I.e. Deposit should return the same or more vault tokens as + /// PreviewDeposit if called in the same transaction. + #[returns(Uint128)] + PreviewDeposit { + /// The of assets to deposit. + assets: Vec, + }, + + /// Returns the ratio in which the underlying assets should be deposited. + /// If no ratio is applicable, should return None. Ratios are expressed + /// as a Vec. This should be interpreted as a deposit should be + /// some multiplicative of the returned vec. + /// + /// A vault does not have to guarantee that this ratio is stable. + #[returns(Vec)] + DepositRatio, + + /// Returns `Uint128` amount of base tokens that would be withdrawn in + /// exchange for redeeming `amount` of vault tokens. + /// + /// Allows an on-chain or off-chain user to simulate the effects of their + /// redeem at the current block, given current on-chain conditions. + /// + /// Must return as close to and no more than the exact amount of base tokens + /// that would be withdrawn in a redeem call in the same transaction. + #[returns(Uint128)] + PreviewRedeem { + /// The amount of vault tokens to preview redeeming. + amount: Uint128, + }, + + /// Returns the amount of assets managed by the vault denominated in underlying + /// tokens. Useful for display purposes. + #[returns(Vec)] + TotalAssets {}, + + /// Returns `Uint128` total amount of vault tokens in circulation. + #[returns(Uint128)] + TotalVaultTokenSupply {}, + + /// The amount of vault tokens that the vault would exchange for the amount + /// of assets provided, in an ideal scenario where all the conditions + /// are met. + /// + /// Useful for display purposes and does not have to confer the exact amount + /// of vault tokens returned by the vault if the passed in assets were + /// deposited. This calculation should not reflect the "per-user" + /// price-per-share, and instead should reflect the "average-user’s" + /// price-per-share, meaning what the average user should expect to see + /// when exchanging to and from. + #[returns(Uint128)] + ConvertToShares { + /// The amount of base tokens to convert to vault tokens. + amount: Vec, + }, + + /// Returns the amount of base tokens that the Vault would exchange for + /// the `amount` of vault tokens provided, in an ideal scenario where all + /// the conditions are met. + /// + /// Useful for display purposes and does not have to confer the exact amount + /// of assets returned by the vault if the passed in vault tokens were + /// redeemed. This calculation should not reflect the "per-user" + /// price-per-share, and instead should reflect the "average-user’s" + /// price-per-share, meaning what the average user should expect to see + /// when exchanging to and from. + #[returns(Uint128)] + ConvertToAssets { + /// The amount of vault tokens to convert to base tokens. + amount: Uint128, + }, + + /// Handle queries of any enabled extensions. + #[returns(Empty)] + VaultExtension(T), +} + +/// Contains QueryMsgs of all enabled extensions. To enable extensions defined +/// outside of this crate, you can define your own `ExtensionQueryMsg` type +/// in your contract crate and pass it in as the generic parameter to QueryMsg +#[cw_serde] +pub enum ExtensionQueryMsg { + #[cfg(feature = "keeper")] + Keeper(KeeperQueryMsg), + #[cfg(feature = "lockup")] + Lockup(LockupQueryMsg), +} + +/// Struct returned from QueryMsg::VaultStandardInfo with information about the +/// used version of the vault standard and any extensions used. +/// +/// This struct should be stored as an Item under the `vault_standard_info` key, +/// so that other contracts can do a RawQuery and read it directly from storage +/// instead of needing to do a costly SmartQuery. +#[cw_serde] +pub struct VaultStandardInfoResponse { + /// The version of the vault standard used. A number, e.g. 1, 2, etc. + pub version: u16, + /// A list of vault standard extensions used by the vault. + /// E.g. ["lockup", "keeper"] + pub extensions: Vec, +} + +/// Returned by QueryMsg::Info and contains information about this vault +#[cw_serde] +pub struct VaultInfoResponse { + /// The tokens used by the vault and accepted for deposits, withdrawals. the value is a denom if it is a native token and a + /// contract address if it is a cw20 token. The value expression of internal accounting is left up to the vault. + pub tokens: Vec, + /// Vault token. The denom if it is a native token and the contract address + /// if it is a cw20 token. + pub vault_token: String, +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/cw4626.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/cw4626.rs new file mode 100644 index 000000000..ab6fbe0a7 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/cw4626.rs @@ -0,0 +1,268 @@ +use crate::msg::{ + ExtensionExecuteMsg, ExtensionQueryMsg, VaultInfoResponse, VaultStandardInfoResponse, +}; +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{to_json_binary, Binary, Coin, CosmosMsg, Empty, StdResult, Uint128, WasmMsg}; +use cw20::{ + AllAccountsResponse, AllAllowancesResponse, AllowanceResponse, BalanceResponse, + DownloadLogoResponse, MarketingInfoResponse, TokenInfoResponse, +}; +use cw20::{Expiration, Logo}; +use schemars::JsonSchema; + +/// The default ExecuteMsg variants that a vault using the Cw4626 extension must +/// implement. This includes all of the variants from the default +/// VaultStandardExecuteMsg, plus the variants from the CW20 standard. This enum +/// can be extended with additional variants by defining an extension enum and +/// then passing it as the generic argument `T` to this enum. +#[cw_serde] +pub enum Cw4626ExecuteMsg { + //-------------------------------------------------------------------------- + // Standard CW20 ExecuteMsgs + //-------------------------------------------------------------------------- + /// Transfer is a base message to move tokens to another account without + /// triggering actions + Transfer { recipient: String, amount: Uint128 }, + /// Send is a base message to transfer tokens to a contract and trigger an + /// action on the receiving contract. + Send { + contract: String, + amount: Uint128, + msg: Binary, + }, + /// Only with "approval" extension. Allows spender to access an additional + /// amount tokens from the owner's (env.sender) account. If expires is + /// Some(), overwrites current allowance expiration with this one. + IncreaseAllowance { + spender: String, + amount: Uint128, + expires: Option, + }, + /// Only with "approval" extension. Lowers the spender's access of tokens + /// from the owner's (env.sender) account by amount. If expires is Some(), + /// overwrites current allowance expiration with this one. + DecreaseAllowance { + spender: String, + amount: Uint128, + expires: Option, + }, + /// Only with "approval" extension. Transfers amount tokens from owner -> + /// recipient if `env.sender` has sufficient pre-approval. + TransferFrom { + owner: String, + recipient: String, + amount: Uint128, + }, + /// Only with "approval" extension. Sends amount tokens from owner -> + /// contract if `env.sender` has sufficient pre-approval. + SendFrom { + owner: String, + contract: String, + amount: Uint128, + msg: Binary, + }, + /// Only with the "marketing" extension. If authorized, updates marketing + /// metadata. Setting None/null for any of these will leave it + /// unchanged. Setting Some("") will clear this field on the contract + /// storage + UpdateMarketing { + /// A URL pointing to the project behind this token. + project: Option, + /// A longer description of the token and it's utility. Designed for + /// tooltips or such + description: Option, + /// The address (if any) who can update this data structure + marketing: Option, + }, + /// If set as the "marketing" role on the contract, upload a new URL, SVG, + /// or PNG for the token + UploadLogo(Logo), + + //-------------------------------------------------------------------------- + // Vault Standard ExecuteMsgs + //-------------------------------------------------------------------------- + /// Called to deposit into the vault. Native assets are passed in the funds + /// parameter. + Deposit { + /// The amount of base tokens to deposit + amount: Uint128, + /// An optional field containing the recipient of the vault token. If + /// not set, the caller address will be used instead. + recipient: Option, + }, + + /// Called to redeem vault tokens and receive assets back from the vault. + /// The native vault token must be passed in the funds parameter, unless the + /// lockup extension is called, in which case the vault token has already + /// been passed to ExecuteMsg::Unlock. + Redeem { + /// Amount of vault tokens to redeem + amount: Uint128, + /// An optional field containing which address should receive the + /// withdrawn base tokens. If not set, the caller address will + /// be used instead. + recipient: Option, + }, + + /// Called to execute functionality of any enabled extensions. + VaultExtension(T), +} + +impl Cw4626ExecuteMsg { + /// Convert a [`Cw4626ExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&self)?, + funds, + } + .into()) + } +} + +/// The default QueryMsg variants that a vault using the Cw4626 extension must +/// implement. This includes all of the variants from the default +/// VaultStandardQueryMsg, plus the variants from the CW20 standard. This enum +/// can be extended with additional variants by defining an extension enum and +/// then passing it as the generic argument `T` to this enum. +#[cw_serde] +#[derive(QueryResponses)] +pub enum Cw4626QueryMsg +where + T: JsonSchema, +{ + //-------------------------------------------------------------------------- + // Standard CW20 QueryMsgs + //-------------------------------------------------------------------------- + /// Returns the current balance of the given address, 0 if unset. + /// Return type: BalanceResponse. + #[returns(BalanceResponse)] + Balance { address: String }, + /// Returns metadata on the contract - name, decimals, supply, etc. + /// Return type: TokenInfoResponse. + #[returns(TokenInfoResponse)] + TokenInfo {}, + /// Only with "allowance" extension. + /// Returns how much spender can use from owner account, 0 if unset. + /// Return type: AllowanceResponse. + #[returns(AllowanceResponse)] + Allowance { owner: String, spender: String }, + /// Only with "marketing" extension + /// Returns more metadata on the contract to display in the client: + /// - description, logo, project url, etc. + /// Return type: MarketingInfoResponse. + #[returns(MarketingInfoResponse)] + MarketingInfo {}, + /// Only with "marketing" extension + /// Downloads the embedded logo data (if stored on chain). Errors if no logo + /// data stored for this contract. + /// Return type: DownloadLogoResponse. + #[returns(DownloadLogoResponse)] + DownloadLogo {}, + /// Only with "enumerable" extension (and "allowances") + /// Returns all allowances this owner has approved. Supports pagination. + /// Return type: AllAllowancesResponse. + #[returns(AllAllowancesResponse)] + AllAllowances { + owner: String, + start_after: Option, + limit: Option, + }, + /// Only with "enumerable" extension + /// Returns all accounts that have balances. Supports pagination. + /// Return type: AllAccountsResponse. + #[returns(AllAccountsResponse)] + AllAccounts { + start_after: Option, + limit: Option, + }, + + //-------------------------------------------------------------------------- + // Vault Standard QueryMsgs + //-------------------------------------------------------------------------- + /// Returns `VaultStandardInfoResponse` with information on the version of + /// the vault standard used as well as any enabled extensions. + #[returns(VaultStandardInfoResponse)] + VaultStandardInfo {}, + + /// Returns `VaultInfoResponse` representing vault requirements, lockup, & + /// vault token denom. + #[returns(VaultInfoResponse)] + Info {}, + + /// Returns `Uint128` amount of vault tokens that will be returned for the + /// passed in `amount` of base tokens. + /// + /// Allows an on-chain or off-chain user to simulate the effects of their + /// deposit at the current block, given current on-chain conditions. + /// + /// Must return as close to and no more than the exact amount of vault + /// tokens that would be minted in a deposit call in the same transaction. + /// I.e. Deposit should return the same or more vault tokens as + /// PreviewDeposit if called in the same transaction. + #[returns(Uint128)] + PreviewDeposit { + /// The amount of base tokens to preview depositing. + amount: Uint128, + }, + + /// Returns `Uint128` amount of base tokens that would be withdrawn in + /// exchange for redeeming `amount` of vault tokens. + /// + /// Allows an on-chain or off-chain user to simulate the effects of their + /// redeem at the current block, given current on-chain conditions. + /// + /// Must return as close to and no more than the exact amount of base tokens + /// that would be withdrawn in a redeem call in the same transaction. + #[returns(Uint128)] + PreviewRedeem { + /// The amount of vault tokens to preview redeeming. + amount: Uint128, + }, + + /// Returns the amount of assets managed by the vault denominated in base + /// tokens. Useful for display purposes, and does not have to confer the + /// exact amount of base tokens. + #[returns(Uint128)] + TotalAssets {}, + + /// Returns `Uint128` total amount of vault tokens in circulation. + #[returns(Uint128)] + TotalVaultTokenSupply {}, + + /// The amount of vault tokens that the vault would exchange for the amount + /// of assets provided, in an ideal scenario where all the conditions + /// are met. + /// + /// Useful for display purposes and does not have to confer the exact amount + /// of vault tokens returned by the vault if the passed in assets were + /// deposited. This calculation should not reflect the "per-user" + /// price-per-share, and instead should reflect the "average-user’s" + /// price-per-share, meaning what the average user should expect to see + /// when exchanging to and from. + #[returns(Uint128)] + ConvertToShares { + /// The amount of base tokens to convert to vault tokens. + amount: Uint128, + }, + + /// Returns the amount of base tokens that the Vault would exchange for + /// the `amount` of vault tokens provided, in an ideal scenario where all + /// the conditions are met. + /// + /// Useful for display purposes and does not have to confer the exact amount + /// of assets returned by the vault if the passed in vault tokens were + /// redeemed. This calculation should not reflect the "per-user" + /// price-per-share, and instead should reflect the "average-user’s" + /// price-per-share, meaning what the average user should expect to see + /// when exchanging to and from. + #[returns(Uint128)] + ConvertToAssets { + /// The amount of vault tokens to convert to base tokens. + amount: Uint128, + }, + + /// Handle queries of any enabled extensions. + #[returns(Empty)] + VaultExtension(T), +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/force_unlock.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/force_unlock.rs new file mode 100644 index 000000000..9c5c9ce3f --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/force_unlock.rs @@ -0,0 +1,57 @@ +use cosmwasm_schema::cw_serde; +use cosmwasm_std::{to_json_binary, Coin, CosmosMsg, StdResult, Uint128, WasmMsg}; + +use crate::cw_vault_standard::msg::{ExtensionExecuteMsg, VaultStandardExecuteMsg}; + +/// Additional ExecuteMsg variants for vaults that enable the ForceUnlock +/// extension. +#[cw_serde] +pub enum ForceUnlockExecuteMsg { + /// Can be called by whitelisted addresses to bypass the lockup and + /// immediately return the base tokens. Used in the event of + /// liquidation. The caller must pass the native vault tokens in the funds + /// field. + ForceRedeem { + /// The address which should receive the withdrawn assets. If not set, + /// the caller address will be used instead. + recipient: Option, + /// The amount of vault tokens to force redeem. + amount: Uint128, + }, + + /// Force withdraw from a position that is already unlocking (Unlock has + /// already been called). + ForceWithdrawUnlocking { + /// The ID of the unlocking position from which to force withdraw + lockup_id: u64, + /// Optional amount of base tokens to be force withdrawn. + /// If None is passed, the entire position will be force withdrawn. + amount: Option, + /// The address which should receive the withdrawn assets. If not set, + /// the assets will be sent to the caller. + recipient: Option, + }, + + /// Update the whitelist of addresses that can call ForceRedeem and + /// ForceWithdrawUnlocking. + UpdateForceWithdrawWhitelist { + /// Addresses to add to the whitelist. + add_addresses: Vec, + /// Addresses to remove from the whitelist. + remove_addresses: Vec, + }, +} + +impl ForceUnlockExecuteMsg { + /// Convert a [`ForceUnlockExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&VaultStandardExecuteMsg::VaultExtension( + ExtensionExecuteMsg::ForceUnlock(self), + ))?, + funds, + } + .into()) + } +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/keeper.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/keeper.rs new file mode 100644 index 000000000..6800ae0ac --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/keeper.rs @@ -0,0 +1,77 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{to_json_binary, Addr, Coin, CosmosMsg, StdResult, WasmMsg}; + +use crate::{ExtensionExecuteMsg, VaultStandardExecuteMsg}; + +/// A job that can be performed by a keeper. +#[cw_serde] +pub struct KeeperJob { + /// The numeric ID of the job + pub id: u64, + /// whether only whitelisted keepers can execute the job or not + pub whitelist: bool, + /// A list of whitelisted addresses that can execute the job + pub whitelisted_keepers: Vec, +} + +/// Additional ExecuteMsg variants for vaults that enable the Keeper extension. +#[cw_serde] +pub enum KeeperExecuteMsg { + /// Callable by vault admin to whitelist a keeper to be able to execute a + /// job + WhitelistKeeper { + /// The ID of the job to whitelist the keeper for + job_id: u64, + /// The address of the keeper to whitelist + keeper: String, + }, + /// Callable by vault admin to remove a keeper from the whitelist of a job + BlacklistKeeper { + /// The ID of the job to blacklist the keeper for + job_id: u64, + /// The address of the keeper to blacklist + keeper: String, + }, + /// Execute a keeper job. Should only be able to be called if + /// [`KeeperQueryMsg::KeeperJobReady`] returns true, and only by whitelisted + /// keepers if the whitelist bool on the KeeperJob is set to true. + ExecuteJob { + /// The ID of the job to execute + job_id: u64, + }, +} + +impl KeeperExecuteMsg { + /// Convert a [`KeeperExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binaryinary(&VaultStandardExecuteMsg::VaultExtension( + ExtensionExecuteMsg::Keeper(self), + ))?, + funds, + } + .into()) + } +} + +/// Additional QueryMsg variants for vaults that enable the Keeper extension. +#[cw_serde] +#[derive(QueryResponses)] +pub enum KeeperQueryMsg { + /// Returns [`Vec`] + #[returns(Vec)] + KeeperJobs {}, + /// Returns [`Vec`] + #[returns(Vec)] + WhitelistedKeepers { + /// The ID of the job to get the whitelisted keepers for + job_id: u64, + }, + /// Returns bool, whether the keeper job can be executed or not + #[returns(bool)] + KeeperJobReady { + /// The ID of the job to check whether it is ready to be executed + job_id: u64, + }, +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/lockup.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/lockup.rs new file mode 100644 index 000000000..0606da68a --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/lockup.rs @@ -0,0 +1,108 @@ +use cosmwasm_schema::{cw_serde, QueryResponses}; +use cosmwasm_std::{to_json_binary, Addr, Coin, CosmosMsg, StdResult, Uint128, WasmMsg}; +#[cfg(not(target_arch = "wasm32"))] +use cw_utils::Duration; +use cw_utils::Expiration; + +use crate::cw_vault_standard::msg::{ExtensionExecuteMsg, VaultStandardExecuteMsg}; + +/// Type for the unlocking position created event emitted on call to `Unlock`. +pub const UNLOCKING_POSITION_CREATED_EVENT_TYPE: &str = "unlocking_position_created"; +/// Key for the lockup id attribute in the "unlocking position created" event +/// that is emitted on call to `Unlock`. +pub const UNLOCKING_POSITION_ATTR_KEY: &str = "lockup_id"; + +/// Additional ExecuteMsg variants for vaults that enable the Lockup extension. +#[cw_serde] +pub enum LockupExecuteMsg { + /// Unlock is called to initiate unlocking a locked position held by the + /// vault. + /// The caller must pass the native vault tokens in the funds field. + /// Emits an event with type `UNLOCKING_POSITION_CREATED_EVENT_TYPE` with + /// an attribute with key `UNLOCKING_POSITION_ATTR_KEY` containing an u64 + /// lockup_id. + /// + /// Like Redeem, this takes an amount so that the same API can be used for + /// CW4626 and native tokens. + Unlock { + /// The amount of vault tokens to unlock. + amount: Uint128, + }, + + /// EmergencyUnlock is called to initiate unlocking a locked position held + /// by the vault. + /// This call should simply unlock `amount` of vault tokens, without performing + /// any other side effects that might cause the transaction to fail. Such + /// as for example compoundning rewards for an LP position. + EmergencyUnlock { + /// The amount of vault tokens to unlock. + amount: Uint128, + }, + + /// Withdraw an unlocking position that has finished unlocking. + WithdrawUnlocked { + /// An optional field containing which address should receive the + /// withdrawn base tokens. If not set, the caller address will be + /// used instead. + recipient: Option, + /// The ID of the expired lockup to withdraw from. + lockup_id: u64, + }, +} + +impl LockupExecuteMsg { + /// Convert a [`LockupExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&VaultStandardExecuteMsg::VaultExtension( + ExtensionExecuteMsg::Lockup(self), + ))?, + funds, + } + .into()) + } +} + +/// Additional QueryMsg variants for vaults that enable the Lockup extension. +#[cw_serde] +#[derive(QueryResponses)] +pub enum LockupQueryMsg { + /// Returns a `Vec` containing all the currently + /// unclaimed lockup positions for the `owner`. + #[returns(Vec)] + UnlockingPositions { + /// The address of the owner of the lockup + owner: String, + /// Return results only after this lockup_id + start_after: Option, + /// Max amount of results to return + limit: Option, + }, + + /// Returns an `UnlockingPosition` info about a specific lockup, by owner + /// and ID. + #[returns(UnlockingPosition)] + UnlockingPosition { + /// The ID of the lockup to query + lockup_id: u64, + }, + + /// Returns `cw_utils::Duration` duration of the lockup of the vault. + #[returns(Duration)] + LockupDuration {}, +} + +/// Info about a currenly unlocking position. +#[cw_serde] +pub struct UnlockingPosition { + /// The ID of the lockup. + pub id: u64, + /// The address of the owner of the lockup. + pub owner: Addr, + /// A `cw_utils::Expiration` containing information about when the position + /// completes unlocking. + pub release_at: Expiration, + /// The amount of base tokens that are being unlocked. + pub base_token_amount: Uint128, +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/mod.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/mod.rs new file mode 100644 index 000000000..543ee6d81 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/extensions/mod.rs @@ -0,0 +1,43 @@ +/// The lockup extension can be used to create vaults where the vault tokens are +/// not immediately reedemable. Instead of normally calling the +/// `VaultStandardExecuteMsg::Redeem` variant, the user has to call the `Unlock` +/// variant on the Lockup extension `ExecuteMsg` and wait for a specified period +/// of time before they can withdraw their base tokens via the +/// `WithdrawUnlocked` variant. +#[cfg(feature = "lockup")] +#[cfg_attr(docsrs, doc(cfg(feature = "lockup")))] +pub mod lockup; + +/// The force unlock extension can be used to create a vault that also +/// implements the `Lockup` extension, but where some whitelisted addresses are +/// allowed to call the `ForceUnlock` variant on the extension `ExecuteMsg` and +/// immediately unlock the vault tokens of the specified user. This is useful if +/// the vault is used with leverage and a liquidator needs to be able to +/// liquidate the tokens locked in the vault. +#[cfg(feature = "force-unlock")] +#[cfg_attr(docsrs, doc(cfg(feature = "force-unlock")))] +pub mod force_unlock; + +/// The keeper extension can be used to add functionality for either whitelisted +/// addresses or anyone to act as a "keeper" for the vault and call functions to +/// perform jobs that need to be done to keep the vault running. +#[cfg(feature = "keeper")] +#[cfg_attr(docsrs, doc(cfg(feature = "keeper")))] +pub mod keeper; + +/// The Cw4626 extension is the only extension provided with in this repo that +/// does not extend the standard `ExecuteMsg` and `QueryMsg` enums with by +/// putting its variants inside of a `VaultExtension` variant. Instead it adds +/// more variants at the top level, namely the variants from the [CW20 +/// standard](https://github.com/CosmWasm/cw-plus/tree/main/packages/cw20) This +/// is inspired by the [ERC-4626 standard on +/// Ethereum](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) +/// and allows the vault to, instead of using a Cosmos native token as the vault +/// token, have the vault contract be it's own vault token by also implementing +/// the CW20 standard. This is useful if you are writing a vault on a chain that +/// does not yet have the [TokenFactory +/// module](https://github.com/CosmWasm/token-factory) available and can +/// therefore not issue a Cosmos native token as the vault token. +#[cfg(feature = "cw4626")] +#[cfg_attr(docsrs, doc(cfg(feature = "cw4626")))] +pub mod cw4626; diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/mod.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/mod.rs new file mode 100644 index 000000000..319efe2c3 --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/mod.rs @@ -0,0 +1,124 @@ +#![cfg_attr(docsrs, feature(doc_cfg))] +//! # CosmWasm Vault Standard +//! +//! A standard interface for tokenized vaults written in CosmWasm. This repo +//! contains a set of `ExecuteMsg` and `QueryMsg` variants that should be +//! implemented by a vault contract that adheres to this standard. +//! +//! ## Vault Standard Fundamentals +//! There are a few things to know about the vault standard: +//! * Each vault has one specific token that is used for deposits, withdrawals +//! and accounting. This token is called the `base token`. +//! * Each vault has a `vault token` that represents the users share in the +//! vault. The number of vault tokens the user receives should be based on the +//! the number of base tokens they deposit. +//! +//! ## How to create a vault contract that adheres to this standard +//! +//! To create a vault contract that adheres to the standard, all you need to do +//! is import the [VaultStandardExecuteMsg] and [VaultStandardQueryMsg] enums +//! and use them in the entrypoints of your contracts. +//! +//! The [VaultStandardExecuteMsg] and [VaultStandardQueryMsg] enums define a set +//! of variants that should be enough to cover most vault contract use cases, +//! and all vaults that adhere to the standard must implement all of the +//! provided default variants. If however your use case requires additional +//! variants, please see the section on [how to use +//! extensions](#how-to-use-extensions). +//! +//! ## Description and specification of ExecuteMsg and QueryMsg variants +//! Please refer to the documentation page for each of the enums +//! [VaultStandardExecuteMsg] and [VaultStandardQueryMsg] for a complete +//! description of each variant. +//! +//! ## How to use Extensions +//! +//! If the standard set of `ExecuteMsg` and `QueryMsg` variants are not enough +//! for your use case, you can include additional ones by defining an extension. +//! The preferred way to do this is by creating a new enum that extends the +//! exported [VaultStandardExecuteMsg] and [VaultStandardQueryMsg] enums. For +//! example: +//! +//! ```ignore +//! pub enum MyExtensionExecuteMsg { +//! MyVariant1 { ... }, +//! MyVariant2 { ... }, +//! } +//! ``` +//! This enum can then be included in an enum with all the Extensions that your +//! vault uses and then be passed in as the generic argument `T` to +//! [`VaultStandardExecuteMsg`]. For example: +//! +//! ```ignore +//! pub enum ExtensionExecuteMsg { +//! MyExtension(MyExtensionExecuteMsg), +//! Lockup(LockupExecuteMsg), +//! } +//! +//! pub type ExecuteMsg = VaultStandardExecuteMsg; +//! ``` +//! +//! Now you can use the `ExecuteMsg` enum in your contract entrypoints instead +//! of the default [VaultStandardExecuteMsg] enum. +//! +//! ## Included Extensions +//! +//! The following extensions are included in this repo: +//! * [Lockup](crate::extensions::lockup) +//! * [ForceUnlock](crate::extensions::force_unlock) +//! * [Keeper](crate::extensions::keeper) +//! * [Cw4626](crate::extensions::cw4626) +//! +//! Each of these extensions are available in this repo via cargo features. To +//! use them, you can import the crate with a feature flag like this: +//! +//! ```toml +//! cw-vault-standard = { version = "0.2.0", features = ["lockup", "force_unlock"] } +//! ``` +//! +//! A short description of each extension can be found below. +//! +//! ### Lockup +//! The lockup extension can be used to create vaults where the vault tokens are +//! not immediately reedemable. Instead of normally calling the +//! [`VaultStandardExecuteMsg::Redeem`] variant, the user has to call the +//! `Unlock` variant on the Lockup extension `ExecuteMsg` and wait for a +//! specified period of time before they can withdraw their base tokens via the +//! `WithdrawUnlocked` variant. +//! +//! ### ForceUnlock +//! The force unlock extension can be used to create a vault that also +//! implements the `Lockup` extension, but where some whitelisted addresses are +//! allowed to call the `ForceUnlock` variant on the extension `ExecuteMsg` and +//! immediately unlock the vault tokens of the specified user. This is useful if +//! the vault is used with leverage and a liquidator needs to be able to +//! liquidate the tokens locked in the vault. +//! +//! ### Keeper +//! The keeper extension can be used to add functionality for either whitelisted +//! addresses or anyone to act as a "keeper" for the vault and call functions to +//! perform jobs that need to be done to keep the vault running. +//! +//! ### Cw4626 +//! The Cw4626 extension is the only extension provided with in this repo that +//! does not extend the default [`VaultStandardExecuteMsg`] and +//! [`VaultStandardQueryMsg`] enums by putting its variants inside of the +//! [`VaultStandardExecuteMsg::VaultExtension`] variant. Instead it adds more +//! variants at the top level, namely the variants from the [CW20 +//! standard](https://github.com/CosmWasm/cw-plus/tree/main/packages/cw20). This +//! is inspired by the [ERC-4626 standard on +//! Ethereum](https://ethereum.org/en/developers/docs/standards/tokens/erc-4626/) +//! and allows the vault to, instead of using a Cosmos native token as the vault +//! token, have the vault contract be it's own vault token by also implementing +//! the CW20 standard. This is useful if you are writing a vault on a chain that +//! does not yet have the [TokenFactory +//! module](https://github.com/CosmWasm/token-factory) available and can +//! therefore not issue a Cosmos native token as the vault token. + +/// Module containing some pre-defined vault standard extensions. +pub mod extensions; +/// Module containing the vault standard ExecutMsg and QueryMsg enums, as well +/// as QueryMsg response types. +pub mod msg; + +pub use msg::*; diff --git a/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/msg.rs b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/msg.rs new file mode 100644 index 000000000..e6757c7fd --- /dev/null +++ b/smart-contracts/osmosis/packages/quasar-types/src/cw_vault_standard/msg.rs @@ -0,0 +1,208 @@ +#[cfg(feature = "force-unlock")] +use crate::cw_vault_standard::extensions::force_unlock::ForceUnlockExecuteMsg; +#[cfg(feature = "keeper")] +use crate::cw_vault_standard::extensions::keeper::{KeeperExecuteMsg, KeeperQueryMsg}; +#[cfg(feature = "lockup")] +use crate::cw_vault_standard::extensions::lockup::{LockupExecuteMsg, LockupQueryMsg}; + +use cosmwasm_schema::{cw_serde, QueryResponses}; +#[cfg(not(target_arch = "wasm32"))] +use cosmwasm_std::Empty; +use cosmwasm_std::{to_json_binary, Coin, CosmosMsg, StdResult, Uint128, WasmMsg}; +use schemars::JsonSchema; + +/// The default ExecuteMsg variants that all vaults must implement. +/// This enum can be extended with additional variants by defining an extension +/// enum and then passing it as the generic argument `T` to this enum. +#[cw_serde] +pub enum VaultStandardExecuteMsg { + /// Called to deposit into the vault. Native assets are passed in the funds + /// parameter. + Deposit { + /// The amount of base tokens to deposit. + amount: Uint128, + /// The optional recipient of the vault token. If not set, the caller + /// address will be used instead. + recipient: Option, + }, + + /// Called to redeem vault tokens and receive assets back from the vault. + /// The native vault token must be passed in the funds parameter, unless the + /// lockup extension is called, in which case the vault token has already + /// been passed to ExecuteMsg::Unlock. + Redeem { + /// An optional field containing which address should receive the + /// withdrawn base tokens. If not set, the caller address will be + /// used instead. + recipient: Option, + /// The amount of vault tokens sent to the contract. In the case that + /// the vault token is a Cosmos native denom, we of course have this + /// information in info.funds, but if the vault implements the + /// Cw4626 API, then we need this argument. We figured it's + /// better to have one API for both types of vaults, so we + /// require this argument. + amount: Uint128, + }, + + /// Called to execute functionality of any enabled extensions. + VaultExtension(T), +} + +impl VaultStandardExecuteMsg { + /// Convert a [`VaultStandardExecuteMsg`] into a [`CosmosMsg`]. + pub fn into_cosmos_msg(self, contract_addr: String, funds: Vec) -> StdResult { + Ok(WasmMsg::Execute { + contract_addr, + msg: to_json_binary(&self)?, + funds, + } + .into()) + } +} + +/// Contains ExecuteMsgs of all enabled extensions. To enable extensions defined +/// outside of this crate, you can define your own `ExtensionExecuteMsg` type +/// in your contract crate and pass it in as the generic parameter to ExecuteMsg +#[cw_serde] +pub enum ExtensionExecuteMsg { + #[cfg(feature = "keeper")] + Keeper(KeeperExecuteMsg), + #[cfg(feature = "lockup")] + Lockup(LockupExecuteMsg), + #[cfg(feature = "force-unlock")] + ForceUnlock(ForceUnlockExecuteMsg), +} + +/// The default QueryMsg variants that all vaults must implement. +/// This enum can be extended with additional variants by defining an extension +/// enum and then passing it as the generic argument `T` to this enum. +#[cw_serde] +#[derive(QueryResponses)] +pub enum VaultStandardQueryMsg +where + T: JsonSchema, +{ + /// Returns `VaultStandardInfoResponse` with information on the version of + /// the vault standard used as well as any enabled extensions. + #[returns(VaultStandardInfoResponse)] + VaultStandardInfo {}, + + /// Returns `VaultInfoResponse` representing vault requirements, lockup, & + /// vault token denom. + #[returns(VaultInfoResponse)] + Info {}, + + /// Returns `Uint128` amount of vault tokens that will be returned for the + /// passed in `amount` of base tokens. + /// + /// Allows an on-chain or off-chain user to simulate the effects of their + /// deposit at the current block, given current on-chain conditions. + /// + /// Must return as close to and no more than the exact amount of vault + /// tokens that would be minted in a deposit call in the same transaction. + /// I.e. Deposit should return the same or more vault tokens as + /// PreviewDeposit if called in the same transaction. + #[returns(Uint128)] + PreviewDeposit { + /// The amount of base tokens to preview depositing. + amount: Uint128, + }, + + /// Returns `Uint128` amount of base tokens that would be withdrawn in + /// exchange for redeeming `amount` of vault tokens. + /// + /// Allows an on-chain or off-chain user to simulate the effects of their + /// redeem at the current block, given current on-chain conditions. + /// + /// Must return as close to and no more than the exact amount of base tokens + /// that would be withdrawn in a redeem call in the same transaction. + #[returns(Uint128)] + PreviewRedeem { + /// The amount of vault tokens to preview redeeming. + amount: Uint128, + }, + + /// Returns the amount of assets managed by the vault denominated in base + /// tokens. Useful for display purposes, and does not have to confer the + /// exact amount of base tokens. + #[returns(Uint128)] + TotalAssets {}, + + /// Returns `Uint128` total amount of vault tokens in circulation. + #[returns(Uint128)] + TotalVaultTokenSupply {}, + + /// The amount of vault tokens that the vault would exchange for the amount + /// of assets provided, in an ideal scenario where all the conditions + /// are met. + /// + /// Useful for display purposes and does not have to confer the exact amount + /// of vault tokens returned by the vault if the passed in assets were + /// deposited. This calculation should not reflect the "per-user" + /// price-per-share, and instead should reflect the "average-user’s" + /// price-per-share, meaning what the average user should expect to see + /// when exchanging to and from. + #[returns(Uint128)] + ConvertToShares { + /// The amount of base tokens to convert to vault tokens. + amount: Uint128, + }, + + /// Returns the amount of base tokens that the Vault would exchange for + /// the `amount` of vault tokens provided, in an ideal scenario where all + /// the conditions are met. + /// + /// Useful for display purposes and does not have to confer the exact amount + /// of assets returned by the vault if the passed in vault tokens were + /// redeemed. This calculation should not reflect the "per-user" + /// price-per-share, and instead should reflect the "average-user’s" + /// price-per-share, meaning what the average user should expect to see + /// when exchanging to and from. + #[returns(Uint128)] + ConvertToAssets { + /// The amount of vault tokens to convert to base tokens. + amount: Uint128, + }, + + /// Handle queries of any enabled extensions. + #[returns(Empty)] + VaultExtension(T), +} + +/// Contains QueryMsgs of all enabled extensions. To enable extensions defined +/// outside of this crate, you can define your own `ExtensionQueryMsg` type +/// in your contract crate and pass it in as the generic parameter to QueryMsg +#[cw_serde] +pub enum ExtensionQueryMsg { + #[cfg(feature = "keeper")] + Keeper(KeeperQueryMsg), + #[cfg(feature = "lockup")] + Lockup(LockupQueryMsg), +} + +/// Struct returned from QueryMsg::VaultStandardInfo with information about the +/// used version of the vault standard and any extensions used. +/// +/// This struct should be stored as an Item under the `vault_standard_info` key, +/// so that other contracts can do a RawQuery and read it directly from storage +/// instead of needing to do a costly SmartQuery. +#[cw_serde] +pub struct VaultStandardInfoResponse { + /// The version of the vault standard used. A number, e.g. 1, 2, etc. + pub version: u16, + /// A list of vault standard extensions used by the vault. + /// E.g. ["lockup", "keeper"] + pub extensions: Vec, +} + +/// Returned by QueryMsg::Info and contains information about this vault +#[cw_serde] +pub struct VaultInfoResponse { + /// The token that is accepted for deposits, withdrawals and used for + /// accounting in the vault. The denom if it is a native token and the + /// contract address if it is a cw20 token. + pub base_token: String, + /// Vault token. The denom if it is a native token and the contract address + /// if it is a cw20 token. + pub vault_token: String, +} diff --git a/smart-contracts/osmosis/packages/quasar-types/src/lib.rs b/smart-contracts/osmosis/packages/quasar-types/src/lib.rs index 6e4123a11..30651505c 100644 --- a/smart-contracts/osmosis/packages/quasar-types/src/lib.rs +++ b/smart-contracts/osmosis/packages/quasar-types/src/lib.rs @@ -1,6 +1,8 @@ pub mod abstract_sdk; pub mod callback; pub mod curve; +pub mod cw_vault_multi_standard; +pub mod cw_vault_standard; pub mod error; pub mod ibc; pub mod ica;