├── workspace ├── miniserve │ ├── README.md │ └── Dockerfile_file_server ├── cosmos-rust-bot │ ├── src │ │ ├── lib.rs │ │ ├── account │ │ │ ├── mod.rs │ │ │ └── wallet.rs │ │ ├── errors.txt │ │ ├── control │ │ │ └── mod.rs │ │ ├── shared │ │ │ └── mod.rs │ │ ├── model │ │ │ ├── requirements │ │ │ │ └── mod.rs │ │ │ └── mod.rs │ │ └── main.rs │ ├── packages │ │ ├── cosmos-rust-server │ │ │ ├── README.md │ │ │ ├── Dockerfile │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ │ └── main.rs │ │ ├── cosmos-rust-telegram-bot │ │ │ ├── src │ │ │ │ ├── lib.rs │ │ │ │ ├── cosmos_rust_bot │ │ │ │ │ ├── mod.rs │ │ │ │ │ ├── static_commands │ │ │ │ │ │ └── mod.rs │ │ │ │ │ └── commands │ │ │ │ │ │ └── mod.rs │ │ │ │ └── main.rs │ │ │ ├── Cargo.toml │ │ │ └── README.md │ │ └── cosmos-rust-signal-bot │ │ │ ├── src │ │ │ ├── lib.rs │ │ │ ├── cosmos_rust_bot │ │ │ │ └── mod.rs │ │ │ ├── presage_extension │ │ │ │ └── mod.rs │ │ │ └── main.rs │ │ │ ├── signal-bot.sh │ │ │ ├── always-run.sh │ │ │ ├── run.sh │ │ │ ├── stop.sh │ │ │ ├── install.sh │ │ │ ├── Cargo.toml │ │ │ └── README.md │ ├── grants │ │ ├── 1.jpeg │ │ ├── 2.jpeg │ │ ├── 3.jpeg │ │ ├── 4.jpeg │ │ ├── 5.jpeg │ │ ├── get_updates.jpeg │ │ ├── fraud_detection.jpeg │ │ └── README.md │ ├── cosmos-rust-bot.json │ ├── DISCLAIMER.txt │ ├── Cargo.toml │ ├── cosmos-rust-bot-feature-list.json │ ├── README.md │ └── LICENSE ├── nginx-reverse-proxy │ ├── README.md │ ├── Dockerfile_nginx_cors │ └── nginx.conf └── Cargo.toml ├── .dockerignore ├── Dockerfile_build ├── Dockerfile_run ├── helper_run_script.sh ├── .gitmodules ├── helper_build_script.sh ├── README.md └── LICENSE /workspace/miniserve/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod shared; -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | workspace 2 | target 3 | tmp 4 | cargo_home 5 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-server/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/src/account/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod wallet; -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-telegram-bot/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod cosmos_rust_bot; -------------------------------------------------------------------------------- /workspace/nginx-reverse-proxy/README.md: -------------------------------------------------------------------------------- 1 | mkdir config and add certificates then build and run 2 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-signal-bot/src/lib.rs: -------------------------------------------------------------------------------- 1 | pub mod cosmos_rust_bot; 2 | pub mod presage_extension; -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/grants/1.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Sc/cosmos-rust-bot/HEAD/workspace/cosmos-rust-bot/grants/1.jpeg -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/grants/2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Sc/cosmos-rust-bot/HEAD/workspace/cosmos-rust-bot/grants/2.jpeg -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/grants/3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Sc/cosmos-rust-bot/HEAD/workspace/cosmos-rust-bot/grants/3.jpeg -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/grants/4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Sc/cosmos-rust-bot/HEAD/workspace/cosmos-rust-bot/grants/4.jpeg -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/grants/5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Sc/cosmos-rust-bot/HEAD/workspace/cosmos-rust-bot/grants/5.jpeg -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/grants/get_updates.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Sc/cosmos-rust-bot/HEAD/workspace/cosmos-rust-bot/grants/get_updates.jpeg -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/grants/fraud_detection.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Philipp-Sc/cosmos-rust-bot/HEAD/workspace/cosmos-rust-bot/grants/fraud_detection.jpeg -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/cosmos-rust-bot.json: -------------------------------------------------------------------------------- 1 | { 2 | "governance_proposal_notifications": true, 3 | "pause_requested": false, 4 | "hot_reload": false, 5 | "remove": false, 6 | "test": true, 7 | "terra_wallet_address": null 8 | } 9 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-signal-bot/signal-bot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" 3 | 4 | args=("$@") 5 | nohup ./cosmos-rust-signal-bot $@ & 6 | 7 | echo $! > ./signal-bot.pid 8 | 9 | echo -e "process id written to ./signal-bot.pid" 10 | -------------------------------------------------------------------------------- /workspace/nginx-reverse-proxy/Dockerfile_nginx_cors: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | 3 | WORKDIR /etc/nginx 4 | COPY ./nginx.conf ./conf.d/default.conf 5 | COPY ./config/*.pem /etc/ 6 | EXPOSE 443 7 | EXPOSE 444 8 | ENTRYPOINT [ "nginx" ] 9 | CMD [ "-g", "daemon off;" ] 10 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-signal-bot/always-run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" 3 | 4 | args=("$@") 5 | 6 | ./signal-bot.sh $@; 7 | sleep 10; 8 | 9 | while true 10 | do 11 | if ! ps -p $(cat ./signal-bot.pid) > /dev/null 12 | then 13 | ./signal-bot.sh $@; 14 | sleep 10 15 | fi 16 | sleep 1 17 | done 18 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rust:latest 2 | 3 | WORKDIR /usr/workspace 4 | 5 | COPY src src/ 6 | COPY Cargo.toml . 7 | RUN cargo build 8 | 9 | EXPOSE 8081 10 | CMD ["cargo run"] 11 | 12 | # sudo docker build -t server . 13 | # sudo docker run --rm -p 8081:8081 -v "$(pwd)../../../../tmp":/usr/workspace/tmp cosmos_rust_server cargo run 14 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-signal-bot/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname "$0")" 4 | 5 | echo -e "checking if ./cosmos-rust-signal-bot is running already and stopping instance" 6 | ./stop.sh 7 | 8 | nohup ./always-run.sh --volatile cosmos-rust-bot & 9 | 10 | echo $! > ./cosmos-rust-signal-bot.pid 11 | 12 | echo -e "process id written to ./cosmos-rust-signal-bot.pid" 13 | echo -e "to stop the bot run: ./stop.sh" 14 | -------------------------------------------------------------------------------- /Dockerfile_build: -------------------------------------------------------------------------------- 1 | # docker container to help building cosmos_rust_bot packages. 2 | 3 | FROM rust:latest 4 | 5 | RUN apt-get update && apt-get -y install openssl 6 | 7 | WORKDIR /usr/workspace 8 | 9 | ENV RUSTFLAGS="--cfg tokio_unstable" 10 | ENV CARGO_HOME=/usr/cargo_home 11 | ENV CARGO_TARGET_DIR=/usr/target 12 | 13 | COPY ./helper_build_script.sh /usr/ 14 | RUN chmod 755 /usr/helper_build_script.sh 15 | 16 | ENTRYPOINT ["/usr/helper_build_script.sh"] 17 | CMD ["test","dev","prod","native","tg-bot","api"] 18 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/DISCLAIMER.txt: -------------------------------------------------------------------------------- 1 | ## Disclaimer 2 | 3 | This software is for educational purposes only. Do not risk money which you are afraid to lose. 4 | USE THE SOFTWARE AT YOUR OWN RISK. THE AUTHOR ASSUMES NO RESPONSIBILITY FOR YOUR USE OF Cosmos-Rust-Bot. 5 | 6 | Always start by running with a dedicated test wallet and do not engage money before you understand how it works 7 | and what results you should expect. 8 | 9 | I strongly recommend you to have coding and Rust knowledge. Do not hesitate to read the source code and understand the 10 | mechanism of this bot. 11 | -------------------------------------------------------------------------------- /Dockerfile_run: -------------------------------------------------------------------------------- 1 | # docker container to help run cosmos_rust_bot packages. 2 | 3 | FROM rust:slim 4 | 5 | WORKDIR /usr/workspace 6 | 7 | COPY ./helper_run_script.sh /usr/ 8 | RUN chmod 755 /usr/helper_run_script.sh 9 | 10 | # settings moved into the /tmp/ volume 11 | #COPY ./workspace/cosmos-rust-bot/cosmos-rust-bot.json . 12 | #COPY ./workspace/cosmos-rust-bot/cosmos-rust-bot-feature-list.json . 13 | 14 | #ADD ./workspace/chain-registry /usr/workspace/chain-registry 15 | # add as volume instead 16 | 17 | #ENV RUST_BACKTRACE=1 18 | 19 | ENTRYPOINT ["/usr/helper_run_script.sh"] 20 | CMD ["dev","prod","native","tg-bot","api"] 21 | 22 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-signal-bot/stop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" 3 | 4 | if [ -f ./cosmos-rust-signal-bot.pid ]; then 5 | cat ./cosmos-rust-signal-bot.pid 6 | kill `cat ./cosmos-rust-signal-bot.pid` 7 | rm ./cosmos-rust-signal-bot.pid 8 | echo "always-run.sh process stopped" 9 | else 10 | echo "always-run.sh process not running" 11 | fi 12 | 13 | if [ -f ./signal-bot.pid ]; then 14 | cat ./signal-bot.pid 15 | kill `cat ./signal-bot.pid` 16 | rm ./signal-bot.pid 17 | echo "signal-bot.sh process stopped" 18 | else 19 | echo "signal-bot.sh process not running" 20 | fi -------------------------------------------------------------------------------- /helper_run_script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | case $1 in 4 | 5 | "dev") 6 | echo "./target/debug/cosmos-rust-bot" 7 | ../target/debug/cosmos-rust-bot 8 | ;; 9 | 10 | "prod") 11 | echo "./target/release/cosmos-rust-bot" 12 | ../target/release/cosmos-rust-bot 13 | ;; 14 | 15 | "native") 16 | echo "./target/release/cosmos-rust-bot" 17 | ../target/release/cosmos-rust-bot 18 | ;; 19 | 20 | "tg-bot") 21 | echo "./target/release/cosmos-rust-telegram-bot" 22 | ../target/release/cosmos-rust-telegram-bot 23 | ;; 24 | "api") 25 | echo "./target/release/cosmos-rust-server" 26 | ../target/release/cosmos-rust-server 27 | ;; 28 | 29 | esac 30 | 31 | echo "exit 0" 32 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cosmos-rust-server" 3 | version = "0.1.0" 4 | authors = ["Philipp Schlütermann "] 5 | description = "" 6 | edition = "2018" 7 | 8 | [dependencies] 9 | cosmos-rust-interface = { workspace = true, default-features = false } 10 | 11 | log.workspace = true 12 | actix-web-httpauth = "*" 13 | actix-cors = "0.6" 14 | actix-service = "2" 15 | actix-web = { version = "4.1", default_features = false, features = ["macros"] } 16 | qstring = "0.7.2" 17 | reqwest = { version = "0.11.12", features = ["json"] } 18 | serde_json = "1.0.87" 19 | serde = { version = "1", features = ["derive"] } 20 | actix-files = "0.6.2" 21 | -------------------------------------------------------------------------------- /workspace/miniserve/Dockerfile_file_server: -------------------------------------------------------------------------------- 1 | FROM rust:latest 2 | 3 | WORKDIR /usr/workspace 4 | 5 | RUN git clone https://github.com/svenstaro/miniserve.git 6 | RUN cd miniserve;RUSTFLAGS="-C target-cpu=native" cargo install --locked --path . 7 | 8 | RUN mkdir ./public 9 | RUN mkdir ./config 10 | CMD ["miniserve"] 11 | 12 | # sudo docker build -t miniserve -f Dockerfile_file_server . 13 | 14 | # without TSL 15 | # sudo docker run --rm -p 8080:8080 -v "$(pwd)/static":/usr/workspace/public miniserve miniserve --auth librelearning:123 --random-route ./public 16 | 17 | # with TSL 18 | # sudo docker run --rm -p 8080:8080 -v "$(pwd)/static":/usr/workspace/public -v "$(pwd)/config":/usr/workspace/config miniserve miniserve --tls-cert ./config/my.cert --tls-key ./config/my.key --auth librelearning:123 --random-route ./public 19 | 20 | 21 | #http://localhost:8080/4e8180/ -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-signal-bot/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname "$0")" 4 | 5 | case $1 in 6 | "dev") 7 | echo "development build" 8 | cargo build 9 | mv ./target/debug/cosmos-rust-signal-bot cosmos-rust-signal-bot 10 | ;; 11 | 12 | "prod") 13 | echo "release build" 14 | cargo build --release 15 | mv ./target/release/cosmos-rust-signal-bot cosmos-rust-signal-bot 16 | ;; 17 | 18 | "native") 19 | echo "optimized release build" 20 | RUSTFLAGS="-C target-cpu=native" cargo build --release 21 | mv ./target/release/cosmos-rust-signal-bot cosmos-rust-signal-bot 22 | ;; 23 | 24 | "") 25 | echo "ERROR: specify one of the following arguments: dev, prod, or native." 26 | exit 27 | ;; 28 | esac 29 | 30 | echo "install.sh finished" 31 | 32 | echo "cosmos-rust-signal-bot executable available as './cosmos-rust-signal-bot'" 33 | echo $(ls -lh cosmos-rust-signal-bot) 34 | echo "" 35 | echo "for convenience use './run.sh' to start the bot and './stop.sh' to stop it." -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-signal-bot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cosmos-rust-signal-bot" 3 | version = "0.4.0" 4 | edition = "2021" 5 | 6 | 7 | [dependencies] 8 | 9 | cosmos-rust-bot = { path = "../../." } # loads the bot_library 10 | 11 | cosmos-rust-interface = { workspace = true, default-features = false, features = ["db"] } # only loads the db functionality 12 | presage = { git = "https://github.com/whisperfish/presage" } 13 | anyhow = "1.0" 14 | chrono = "0.4" 15 | directories = "3.0" 16 | env_logger = "0.7" 17 | futures = "0.3" 18 | hex = "0.4" 19 | log = "0.4" 20 | mime_guess = "2.0" 21 | rand = "0.7" 22 | serde_json = "1.0" 23 | structopt = "0.3" 24 | tempfile = "3.3" 25 | url = "2.2.2" 26 | tokio = { version = "1.0", features = ["macros", "rt-multi-thread", "io-std", "io-util"] } 27 | qr2term = { version = "0.2.2" } 28 | regex = "1.6.0" 29 | heck = "0.4.0" 30 | sled = { version = "0.34.7", features = ["compression"] } 31 | 32 | [patch.crates-io] 33 | "curve25519-dalek" = { git = 'https://github.com/signalapp/curve25519-dalek', branch = 'lizard2' } -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-telegram-bot/Cargo.toml: -------------------------------------------------------------------------------- 1 | 2 | [package] 3 | name = "cosmos-rust-telegram-bot" 4 | version = "1.0.0" 5 | edition = "2021" 6 | 7 | 8 | [dependencies] 9 | teloxide = { version = "0.10", features = ["macros"] } 10 | pretty_env_logger = "0.4" 11 | tokio = { workspace = true, features = ["full","rt-multi-thread", "macros"] } 12 | 13 | #cosmos-rust-bot = { path = "../../." } # loads the bot_library 14 | cosmos-rust-interface = { workspace = true, default-features = false, features = ["db"] } # only loads the db functionality 15 | #cosmos-rust-interface = { git = "https://github.com/Philipp-Sc/cosmos-rust-interface.git", default-features = false, features = ["db"] } # only loads the db functionality 16 | anyhow.workspace = true 17 | chrono.workspace = true 18 | hex.workspace = true 19 | log.workspace = true 20 | serde_json.workspace = true 21 | regex.workspace = true 22 | heck.workspace = true 23 | sled = { workspace = true, features = ["compression"] } 24 | lazy_static = {workspace = true} 25 | 26 | futures = "0.3" 27 | mime_guess = "2.0" 28 | rand = "0.8.5" 29 | url = "2.2.2" -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "workspace/cosmos-rust-bot/chain-registry"] 2 | path = workspace/cosmos-rust-bot/chain-registry 3 | url = https://github.com/cosmos/chain-registry.git 4 | branch = master 5 | [submodule "workspace/cosmos-rust-interface"] 6 | path = workspace/cosmos-rust-interface 7 | url = https://github.com/Philipp-Sc/cosmos-rust-interface.git 8 | branch = main 9 | [submodule "workspace/cosmos-rust-package"] 10 | path = workspace/cosmos-rust-package 11 | url = https://github.com/Philipp-Sc/cosmos-rust-package.git 12 | branch = main 13 | [submodule "workspace/cosmos-rust-development"] 14 | path = workspace/cosmos-rust-development 15 | url = https://github.com/Philipp-Sc/cosmos-rust-development.git 16 | branch = main 17 | [submodule "workspace/chain-registry"] 18 | path = workspace/chain-registry 19 | url = https://github.com/cosmos/chain-registry.git 20 | [submodule "workspace/rust-bert-fraud-detection"] 21 | path = workspace/rust-bert-fraud-detection 22 | url = https://github.com/Philipp-Sc/rust-bert-fraud-detection.git 23 | [submodule "rust-bert-fraud-detection"] 24 | update = rebase 25 | [submodule "rust-bert-fraud-detectiontest"] 26 | update = rebase 27 | [submodule "workspace/rust-openai-gpt-tools"] 28 | path = workspace/rust-openai-gpt-tools 29 | url = https://github.com/Philipp-Sc/rust-openai-gpt-tools.git 30 | [submodule "workspace/rust-link-to-text"] 31 | path = workspace/rust-link-to-text 32 | url = https://github.com/Philipp-Sc/rust-link-to-text.git 33 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-telegram-bot/README.md: -------------------------------------------------------------------------------- 1 |
2 |

Cosmos Rust Telegram Bot

3 |

Telegram Notifications

4 | 5 |
6 |
7 | 8 | ### [Install](#install) · [Usage](#usage) 9 | 10 | > :warning: For security reasons is only possible to use cosmos-rust-telegram-bot to query or receive notifications. For other use cases setup cosmos-rust-signal-bot. 11 | 12 | ## How it works 13 | 14 | #### Configuration 15 | 16 | * **cosmos-rust-bot** writes the current data (via cosmos-rust-interface) to an embedded database. 17 | * Using UNIX Sockets **cosmos-rust-bot** communicates with **cosmos-rust-telegram-bot**: 18 | - **cosmos-rust-bot**: request notification(s) for a given query 19 | - **cosmos-rust-telegram-bot**: receive notification(s) 20 | Note: **cosmos-rust-bot** issues notifications either directly after a request or when the data related to a subscription was updated. 21 | * **cosmos-rust-telegram-bot** manages its notification in its own embedded database. 22 | 23 | ## Install 24 | 25 | **Build cosmos-rust-telegram-bot** 26 | 27 | * `cd ./packages/cosmos-rust-telegram-bot` 28 | * `RUSTFLAGS="--cfg tokio_unstable" cargo build` 29 | 30 | ## Usage 31 | 32 | ### Run cosmos-rust-signal-bot 33 | 34 | * If you already started the cosmos-rust-bot then you can use the terra-rust-telegram-bot. 35 | 36 | * `cd ./packages/cosmos-rust-telegram-bot` 37 | * `RUST_LOG=error,debug,info target/debug/cosmos-rust-telegram-bot` 38 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cosmos-rust-bot" 3 | authors = ["Philipp Schlütermann "] 4 | description = "" 5 | repository = "https://github.com/Philipp-Sc/cosmos-rust-bot" 6 | version = "2.0.0" 7 | edition = "2021" 8 | 9 | [lib] 10 | name = "bot_library" 11 | path = "src/lib.rs" 12 | 13 | [[bin]] 14 | name = "cosmos-rust-bot" 15 | required-features = ["build-binary"] 16 | 17 | 18 | [features] 19 | build-binary = ["lazy_static","log","env_logger","cosmos-rust-interface", "anyhow", "enum-as-inner", "heck","litcrypt","notify","regex","secstr","strum","strum_macros"] 20 | 21 | [dependencies] 22 | cosmos-rust-interface = { workspace = true, optional = true } 23 | #cosmos-rust-interface = { git = "https://github.com/Philipp-Sc/cosmos-rust-interface.git", optional = true } 24 | #cosmos-rust-package = { git = "https://github.com/Philipp-Sc/cosmos-rust-package.git", optional = true } 25 | anyhow = { workspace = true, optional = true } 26 | serde = { workspace = true, features = ["derive"] } 27 | serde_json.workspace = true 28 | rust_decimal.workspace = true 29 | enum-as-inner = { workspace = true, optional = true } 30 | heck = { workspace = true, optional = true } 31 | regex = { workspace = true, optional = true } 32 | strum = { workspace = true, optional = true } 33 | strum_macros = { workspace = true, optional = true } 34 | secstr = { version = "0.5.0", optional = true } 35 | litcrypt = { version = "0.3", optional = true } 36 | notify = { version = "4.0.17", optional = true } 37 | 38 | log = { workspace = true, optional = true } 39 | env_logger = { workspace = true, optional = true } 40 | lazy_static = { workspace = true, optional = true } -------------------------------------------------------------------------------- /helper_build_script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | WALLET_RS=$(find . -name "wallet.rs") 4 | sed -i 's/lc!(".*").to_string().into_bytes();/lc!("'$(openssl rand -hex 256)'").to_string().into_bytes();/g' $WALLET_RS 5 | echo "updated secret in $WALLET_RS" 6 | 7 | export LITCRYPT_ENCRYPT_KEY=$(openssl rand -hex 256) 8 | echo "created secret LITCRYPT_ENCRYPT_KEY" 9 | 10 | case $1 in 11 | 12 | "update") 13 | echo "update" 14 | cargo update 15 | ;; 16 | 17 | "test") 18 | echo "test" 19 | cargo test --package cosmos-rust-bot --features build-binary -- --nocapture 20 | ;; 21 | 22 | "dev") 23 | echo "cargo build --features build-binary" 24 | cargo build --package cosmos-rust-bot --features build-binary 25 | ;; 26 | 27 | "prod") 28 | echo "cargo build --features build-binary --release" 29 | cargo build --package cosmos-rust-bot --features build-binary --release 30 | ;; 31 | 32 | "native") 33 | echo "RUSTFLAGS=""$RUSTFLAGS" -C target-cpu=native" cargo build --package cosmos-rust-bot --features build-binary --release " 34 | RUSTFLAGS="$RUSTFLAGS -C target-cpu=native" cargo build --package cosmos-rust-bot --features build-binary --release 35 | ;; 36 | 37 | "tg-bot") 38 | echo "RUSTFLAGS=""$RUSTFLAGS" -C target-cpu=native" cargo build --package cosmos-rust-telegram-bot --release " 39 | RUSTFLAGS="$RUSTFLAGS -C target-cpu=native" cargo build --package cosmos-rust-telegram-bot --release 40 | ;; 41 | 42 | "api") 43 | echo "RUSTFLAGS=""$RUSTFLAGS" -C target-cpu=native" cargo build --package cosmos-rust-server --release " 44 | RUSTFLAGS="$RUSTFLAGS -C target-cpu=native" cargo build --package cosmos-rust-server --release 45 | ;; 46 | esac 47 | 48 | echo "exit 0" 49 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/src/account/wallet.rs: -------------------------------------------------------------------------------- 1 | use secstr::*; 2 | // https://github.com/unrelentingtech/secstr 3 | 4 | /* (defined in main.rs, needs to be at the root) 5 | #[macro_use] 6 | extern crate litcrypt; 7 | // https://github.com/anvie/litcrypt.rs 8 | use_litcrypt!(); 9 | 10 | */ 11 | 12 | fn xor_cipher(text: String) -> String { 13 | let mut v1: Vec = text.to_string().into_bytes(); 14 | /* INFO: Action needed! 15 | * 16 | * You need to replace the string within lc!("...") with a random string of at least 256 characters. 17 | * The secret will be encrypting during compilation time and 18 | * will remain encrypted in both disk and memory during runtime until it is used. 19 | * 20 | * It will be used to encrypt/decrypt the seed phrase! 21 | * This provides additional security in the case when someone is able to access the RAM due to a memory leak or exploit. 22 | */ 23 | let secret: Vec = lc!("9c9d2f0f9ef476137eb392d5cb347035840786dde834188148daf42d1bbb98ca792fef3fa7a4b32b230737a55cdc8932889cc4741d77bc864c57ba973ca6950c40b1139a6fc8ac744e673307cd7f9a624be5f7bcc2d4f7904e24122a3c5788b94af78ec60c7a0c75981aab5a68b8273466436f177f2136131a625e57ab352ce63ee6d2ad02b1ef715e8f1cd2a6e1b36bf7eaa3492df9405f1ddff55eba673dffeee131fcec54bf79012f82e62ec9ef2e16bdc1985d9ab4a12fc7b4b801eec004dc3d2b89761e66bdcfbebfae37e6a1d6cf634ee4747c91152fbec9df65d7eb134791fb8aafd25cdcda56b2dd96586cb8e48b305e415b0d2475431904bb23649e").to_string().into_bytes(); 24 | 25 | v1.iter_mut() 26 | .zip(secret.iter()) 27 | .for_each(|(x1, x2)| *x1 ^= *x2); 28 | return String::from_utf8_lossy(&v1).to_string(); 29 | } 30 | 31 | pub fn encrypt_text_with_secret(text: String) -> SecUtf8 { 32 | return SecUtf8::from(xor_cipher(text)); 33 | } 34 | 35 | pub fn decrypt_text_with_secret(secret: &SecUtf8) -> String { 36 | return xor_cipher(secret.unsecure().to_string()); 37 | } -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-telegram-bot/src/cosmos_rust_bot/mod.rs: -------------------------------------------------------------------------------- 1 | use cosmos_rust_interface::utils::entry::UserMetaData; 2 | 3 | mod static_commands; 4 | mod commands; 5 | 6 | use static_commands::*; 7 | use commands::*; 8 | 9 | 10 | pub async fn handle_message(user_id: u64, message: String, db: &sled::Db) { 11 | 12 | let mut msg = String::with_capacity(message.len()); 13 | message.trim().to_lowercase().replace("/","").replace("_"," ").replace("\n","").split_whitespace().for_each(|w| { 14 | if !msg.is_empty() { 15 | msg.push(' '); 16 | } 17 | msg.push_str(w); 18 | }); 19 | 20 | let msg_for_query = msg.replace(" subscribe","").replace(" unsubscribe",""); 21 | 22 | let user_hash = UserMetaData::user_hash(user_id); 23 | 24 | handle_start(user_hash,&msg,db) 25 | .or_else(|_|handle_about(user_hash,&msg,db)) 26 | .or_else(|_|handle_help_tasks(user_hash,&msg,db)) 27 | .or_else(|_|handle_help_governance_proposals(user_hash,&msg,db)) 28 | .or_else(|_|handle_common_subs(user_hash,&msg,db)) 29 | .or_else(|_|handle_tasks(user_hash,&msg,db)) 30 | .or_else(|_|handle_governance_proposals(user_hash,&msg,db)) 31 | .or_else(|_|handle_proposal_by_id(user_hash,&msg,db)) 32 | .or_else(|_|handle_latest_proposals(user_hash,&msg,db)) 33 | .or_else(|_|handle_proposals_by_status(user_hash,&msg,db)) 34 | .or_else(|_|handle_tasks_logs_errors_debug(user_hash,&msg, &msg_for_query,db)) 35 | .or_else(|_|handle_tasks_count_list_history(user_hash,&msg, &msg_for_query,db)) 36 | .or_else(|_|handle_subscribe_unsubscribe(user_hash,&msg, &msg_for_query,db)) 37 | .or_else(|_|handle_gov_prpsl(user_hash,&msg, &msg_for_query,db)) 38 | .or_else(|_|handle_register(user_hash,&msg,db)) 39 | .or_else(|_|handle_verify(user_hash,&msg,db)) 40 | .or_else(|_|handle_unknown_command(user_hash,db)).ok(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/src/errors.txt: -------------------------------------------------------------------------------- 1 | ERROR teloxide::error_handlers > An error from the update listener: Network(reqwest::Error { kind: Request, url: Url { scheme: "https", cannot_be_a_base: false, username: "", password: None, host: Some(Domain("api.telegram.org")), port: None, path: "/token:redacted/GetUpdates", query: None, fragment: None }, source: hyper::Error(Io, Os { code: 104, kind: ConnectionReset, message: "Connection reset by peer" }) }) 2 | thread '' panicked at 'called `Option::unwrap()` on a `None` value', /home/user1/.cargo/git/checkouts/cosmos-rust-interface-1a4acf9fe14fe855/d4c928e/src/utils/entry/db/notification/mod.rs:84:50 3 | note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace 4 | thread 'tokio-runtime-worker' panicked at 'called `Result::unwrap()` on an `Err` value: Could not create stream 5 | 6 | Caused by: 7 | Connection refused (os error 111)', /home/user1/terra/cosmos-rust-bot/packages/cosmos-rust-telegram-bot/src/cosmos_rust_bot/mod.rs:532:53 8 | thread 'tokio-runtime-worker' panicked at 'TX is dead: SendError(Update { id: 286723767, kind: Message(Message { id: 4005, date: 2022-09-21T15:00:29Z, chat: Chat { id: ChatId(5156515412), kind: Private(ChatPrivate { username: Some("philipp_sc"), first_name: Some("Philipp"), last_name: Some("Sc"), bio: None, has_private_forwards: None }), photo: None, pinned_message: None, message_auto_delete_time: None }, via_bot: None, kind: Common(MessageCommon { from: Some(User { id: UserId(5156515412), is_bot: false, first_name: "Philipp", last_name: Some("Sc"), username: Some("philipp_sc"), language_code: Some("de"), is_premium: false, added_to_attachment_menu: false }), sender_chat: None, author_signature: None, forward: None, reply_to_message: None, edit_date: None, media_kind: Text(MediaText { text: "/tasks_history_100", entities: [MessageEntity { kind: BotCommand, offset: 0, length: 18 }] }), reply_markup: None, is_automatic_forward: false, has_protected_content: false }) }) })', /home/user1/.cargo/registry/src/github.com-1ecc6299db9ec823/teloxide-0.10.1/src/dispatching/dispatcher.rs:398:43 9 | -------------------------------------------------------------------------------- /workspace/Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "cosmos-rust-bot", 4 | "cosmos-rust-interface", 5 | "cosmos-rust-package", 6 | "cosmos-rust-bot/packages/cosmos-rust-telegram-bot", 7 | "cosmos-rust-bot/packages/cosmos-rust-server", 8 | ] 9 | 10 | exclude = [ 11 | "./rust-bert-fraud-detection/socket_ipc", 12 | "./rust-bert-fraud-detection/package", 13 | "./rust-openai-gpt-tools/socket_ipc", 14 | "./rust-openai-gpt-tools/package", 15 | "./rust-link-to-text/socket_ipc", 16 | "./rust-link-to-text/package", 17 | ] 18 | 19 | resolver = "2" 20 | 21 | [workspace.dependencies] 22 | cosmos-rust-interface = { path = "./cosmos-rust-interface" } 23 | cosmos-rust-package = { path = './cosmos-rust-package' } 24 | 25 | cosmrs = {git = "https://github.com/cosmos/cosmos-rust.git" } 26 | 27 | cosmos-sdk-proto = "0.17.0" 28 | osmosis-std = "0.15.0" 29 | 30 | 31 | rust-bert-fraud-detection-socket-ipc = { path = "./rust-bert-fraud-detection/socket_ipc" } 32 | rust-openai-gpt-tools-socket-ipc = { path = "./rust-openai-gpt-tools/socket_ipc" } 33 | rust-link-to-text-socket-ipc = { path = "./rust-link-to-text/socket_ipc" } 34 | chrono = "^0.4" 35 | tokio = { version = "1.27.0" } 36 | serde = "1.0" 37 | serde_json = "1.0" 38 | anyhow = "1.0" 39 | sled = { version = "0.34.7" } 40 | bincode = "1.3.3" 41 | rust_decimal = "1.12.2" 42 | strum = "0.24" 43 | strum_macros = "0.24" 44 | regex = "1.6.0" 45 | enum-as-inner = "0.5.1" 46 | heck = "0.4.0" 47 | reqwest = "0.11.6" 48 | hex = "0.4.3" 49 | log = "0.4.14" 50 | env_logger = "0.9.3" 51 | lazy_static = "1.4.0" 52 | linkify = "0.9.0" 53 | minify-html = "0.10.8" 54 | rand = "0.8.5" 55 | 56 | base64 = "0.13.0" 57 | secp256k1 = "0.20.3" 58 | 59 | nnsplit = "0.5.8" 60 | 61 | 62 | [patch.crates-io] 63 | cosmos-sdk-proto = { git = "https://github.com/Philipp-Sc/cosmos-rust-development.git" , branch= 'patch-1' } 64 | 65 | #[patch.crates-io] 66 | #"curve25519-dalek" = { git = 'https://github.com/signalapp/curve25519-dalek', branch = 'lizard2' } 67 | 68 | [profile.release] 69 | # Enable link-time optimization, eliminates more code and inlines across crate boundaries. 70 | # Default: false 71 | lto = true 72 | 73 | # codegen-units of 1 gives best optimization, but disables parallel building. 74 | # Default: 16 75 | codegen-units = 1 76 | 77 | # The default optimization level is 3 for release mode builds. 78 | # 0 means disable optimization and is the default for debug mode buids. 79 | # (Setting opt-level=1 for debug builds is a good way of speeding them up a bit.) 80 | # "s" means optimize for size, "z" reduces size even more. 81 | opt-level = 3 82 | 83 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/src/control/mod.rs: -------------------------------------------------------------------------------- 1 | /*use std::collections::HashMap; 2 | use std::sync::Arc; 3 | use cosmos_rust_interface::cosmos_rust_package::tokio::sync::{Mutex}; 4 | use cosmos_rust_interface::cosmos_rust_package::tokio::task::JoinSet; 5 | use core::pin::Pin; 6 | use core::future::Future; 7 | use cosmos_rust_interface::utils::response::ResponseResult; 8 | 9 | use crate::model::get_timestamps_of_tasks; 10 | //use crate::model::try_register_function; 11 | use cosmos_rust_interface::utils::entry::{Maybe}; 12 | use crate::model::access_maybe; 13 | */ 14 | /* 15 | pub async fn data_is_outdated(memory: HashMap>>>>, req: &[&str]) -> bool { 16 | match access_maybe(&memory, "latest_transaction").await { 17 | Maybe { data: Ok(_), timestamp } => { 18 | let mut timestamps = get_timestamps_of_tasks(&memory).await.iter().filter(|x| req.contains(&x.0.as_str())).map(|x| x.1).collect::>(); 19 | timestamps.sort(); 20 | if timestamps.len() > 0 && timestamps[0] + 10 > timestamp { 21 | return true; 22 | } 23 | return false; 24 | } 25 | Maybe { data: Err(_), .. } => { 26 | return false; 27 | } 28 | } 29 | }*/ 30 | /* 31 | pub async fn try_run_function(join_set: &mut JoinSet<()>, memory: &HashMap>>>>, task: Pin> + Send + 'static>>, key: &str, is_test: bool) { 32 | let timeout_duration = 120u64; 33 | /* if task hangs for some reason (awaiting data, performing estimate, broadcasting transaction) then timeout */ 34 | 35 | let mut block_duration_after_resolve = 1i64; 36 | /* a small duration is optimal, since the data is already there */ 37 | /* only issue is if there just was a transaction, this is handled by ensuring that the relevant data is recent enough.*/ 38 | 39 | if is_test { 40 | // each call executes an estimate, therefore have higher delay to not spam estimates. 41 | // since test mode does not perform transactions, there is no downside by doing this. 42 | block_duration_after_resolve = 30i64; 43 | } 44 | try_register_function(join_set, memory, key.to_owned(), task, timeout_duration, block_duration_after_resolve).await; 45 | /* will register and run task if conditions are right */ 46 | }*/ 47 | 48 | 49 | 50 | 51 | /* 52 | register_value(memory,"anchor_auto_stake_airdrops".to_string(),msg.to_owned()).await; 53 | register_value(memory,"latest_transaction".to_string(),msg.to_owned()).await; 54 | 55 | */ -------------------------------------------------------------------------------- /workspace/nginx-reverse-proxy/nginx.conf: -------------------------------------------------------------------------------- 1 | upstream file-server { 2 | server 172.17.0.1:8080; 3 | } 4 | upstream api { 5 | server 172.17.0.1:8081; 6 | } 7 | 8 | server { 9 | listen 443 ssl; 10 | ssl_certificate /etc/fullchain.pem; 11 | ssl_certificate_key /etc/privkey.pem; 12 | server_name libreai.de; 13 | 14 | location / { 15 | 16 | # if ($request_method = 'OPTIONS') { 17 | # add_header 'Access-Control-Max-Age' 1728000; 18 | # add_header 'Access-Control-Allow-Origin' '*'; 19 | # add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent, 20 | # X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; 21 | # add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH'; 22 | # add_header 'Content-Type' 'application/json'; 23 | # add_header 'Content-Length' 0; 24 | # return 204; 25 | # } 26 | 27 | # add_header 'Access-Control-Allow-Origin' '*'; 28 | # add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent, 29 | # X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; 30 | # add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH'; 31 | 32 | 33 | #proxy_read_timeout 300s; 34 | #proxy_connect_timeout 75s; 35 | proxy_pass http://file-server/; 36 | } 37 | } 38 | 39 | server { 40 | listen 444 ssl; 41 | ssl_certificate /etc/fullchain.pem; 42 | ssl_certificate_key /etc/privkey.pem; 43 | server_name libreai.de; 44 | 45 | location / { 46 | # if ($request_method = 'OPTIONS') { 47 | # add_header 'Access-Control-Max-Age' 1728000; 48 | # add_header 'Access-Control-Allow-Origin' '*'; 49 | # add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent, 50 | # X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; 51 | # add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH'; 52 | # add_header 'Content-Type' 'application/json'; 53 | # add_header 'Content-Length' 0; 54 | # return 204; 55 | # } 56 | 57 | # add_header 'Access-Control-Allow-Origin' '*'; 58 | # add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent, 59 | # X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range'; 60 | # add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH'; 61 | 62 | 63 | proxy_pass http://api/; 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-signal-bot/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |

Cosmos Rust Signal Bot

5 |

Signal Messenger integration

6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | ### [Install](#install) · [Usage](#usage) 15 | 16 | > :warning: It is recommended to use a dedicated Signal account for cosmos-rust-bot. 17 | 18 | > :warning: The Signal Configuration is kept in-memory and secured via the [secrets crate](https://github.com/stouset/secrets) 19 | 20 | ## How it works 21 | 22 | #### Configuration 23 | 24 | * **cosmos-rust-bot** writes the current data (via cosmos-rust-interface) to an embedded database. 25 | * Using UNIX Sockets **cosmos-rust-bot** communicates with **cosmos-rust-signal-bot**: 26 | - **cosmos-rust-bot**: request notification(s) for a given query 27 | - **cosmos-rust-signal-bot**: receive notification(s) 28 | Note: **cosmos-rust-bot** issues notifications either directly after a request or when the data related to a subscription was updated. 29 | * cosmos-rust-signal-bot manages its notification in its own embedded database. 30 | 31 | ## Install 32 | 33 | **Build cosmos-rust-signal-bot** 34 | 35 | * `cd ./packages/cosmos-rust-signal-bot` 36 | * `./install.sh dev` 37 | 38 | ## Usage 39 | 40 | ### Run cosmos-rust-signal-bot 41 | 42 | * If you already started the cosmos-rust-bot then you can use the cosmos-rust-signal-bot. 43 | 44 | * `cd ./packages/cosmos-rust-signal-bot` 45 | 46 | *The signal client is still experimental. 47 | The following script is configured to restart the signal-bot in case it crashes unexpectedly.* 48 | 49 | * `./run.sh` (run the signal-bot) 50 | * run `cat nohup.out` to view the QR code to link device. The configuration is stored safely in-memory as long as **cosmos-rust-signal-bot** runs. 51 | Note: if you want a persistent device linkage edit `./run.sh` and: 52 | - remove `--volatile` 53 | - add `--try-use-linked-device` after `cosmos-rust-bot` (this will re-use your existing configuration) 54 | * `./stop.sh` (stop the signal-bot) 55 | 56 | 57 | * Within your **Signal Messenger App** in your Contact search bar type **"Note to Self"**. 58 | 59 | ## Uninstall 60 | 61 | * unlink your device within your Signal Messenger App. 62 | * `ls ~/.config/presage` shows you the signal client data. 63 | * remove it via `rm -rf ~/.config/presage`. 64 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/src/shared/mod.rs: -------------------------------------------------------------------------------- 1 | use serde::Deserialize; 2 | use serde::Serialize; 3 | use rust_decimal::Decimal; 4 | use std::str::FromStr; 5 | use std::fs; 6 | use std::io; 7 | use std::hash::{Hash}; 8 | use serde_json::{Value}; 9 | 10 | // todo: add functionality to add/remove/edit settings in-memory & the settings file on disk (load, edit, save). 11 | 12 | #[derive(Serialize, Deserialize, Debug, Clone)] 13 | pub struct UserSettings { 14 | pub governance_proposal_notifications: bool, 15 | pub pause_requested: bool, 16 | pub hot_reload: bool, 17 | pub remove: bool, 18 | pub test: bool, 19 | pub terra_wallet_address: Option, 20 | } 21 | 22 | impl Default for UserSettings { 23 | fn default() -> UserSettings { 24 | UserSettings { 25 | governance_proposal_notifications: true, 26 | pause_requested: false, 27 | hot_reload: false, 28 | remove: false, 29 | test: true, 30 | terra_wallet_address: None, 31 | } 32 | } 33 | } 34 | 35 | pub fn get_input(prompt: &str) -> String { 36 | println!("{}", prompt); 37 | let mut input = String::new(); 38 | match io::stdin().read_line(&mut input) { 39 | Ok(_goes_into_input_above) => {} 40 | Err(_no_updates_is_fine) => {} 41 | } 42 | input.trim().to_string() 43 | } 44 | 45 | pub fn load_asset_whitelist(path: &str) -> Value { 46 | serde_json::json!({ 47 | "contracts": serde_json::from_str::(&fs::read_to_string(format!("{}contracts.json", path)).unwrap()).unwrap(), 48 | "pairs_dex": serde_json::from_str::(&fs::read_to_string(format!("{}pairs.dex.json", path)).unwrap()).unwrap(), 49 | "pairs": serde_json::from_str::(&fs::read_to_string(format!("{}pairs.json", path)).unwrap()).unwrap(), 50 | "tokens": serde_json::from_str::(&fs::read_to_string(format!("{}tokens.json", path)).unwrap()).unwrap(), 51 | "custom": serde_json::from_str::(&fs::read_to_string(format!("{}custom.json", path)).unwrap()).unwrap(), 52 | }) 53 | } 54 | 55 | pub fn load_user_settings(path: &str) -> UserSettings { 56 | let user_settings: UserSettings = match fs::read_to_string(path) { 57 | Ok(file) => { 58 | match serde_json::from_str(&file) { 59 | Ok(res) => { 60 | res 61 | } 62 | Err(err) => { 63 | println!("{:?}", err); 64 | Default::default() 65 | } 66 | } 67 | } 68 | Err(err) => { 69 | println!("{:?}", err); 70 | Default::default() 71 | } 72 | }; 73 | if user_settings.remove { 74 | let res = fs::remove_file(path); 75 | println!("{:?}", res); 76 | } 77 | user_settings 78 | } 79 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/cosmos-rust-bot-feature-list.json: -------------------------------------------------------------------------------- 1 | [{"name":"governance_proposal_notifications","requirements":[{"name":"osmosis_governance_voting_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"osmosis","proposal_status":"voting_period"}},{"name":"osmosis_governance_deposit_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"osmosis","proposal_status":"deposit_period"}},{"name":"osmosis_governance_failed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"osmosis","proposal_status":"failed"}},{"name":"osmosis_governance_passed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"osmosis","proposal_status":"passed"}},{"name":"osmosis_governance_rejected_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"osmosis","proposal_status":"rejected"}},{"name":"terra_governance_voting_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra","proposal_status":"voting_period"}},{"name":"terra_governance_deposit_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra","proposal_status":"deposit_period"}},{"name":"terra_governance_failed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra","proposal_status":"failed"}},{"name":"terra_governance_passed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra","proposal_status":"passed"}},{"name":"terra_governance_rejected_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra","proposal_status":"rejected"}},{"name":"terra2_governance_voting_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra2","proposal_status":"voting_period"}},{"name":"terra2_governance_deposit_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra2","proposal_status":"deposit_period"}},{"name":"terra2_governance_failed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra2","proposal_status":"failed"}},{"name":"terra2_governance_passed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra2","proposal_status":"passed"}},{"name":"terra2_governance_rejected_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"terra2","proposal_status":"rejected"}},{"name":"juno_governance_voting_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"juno","proposal_status":"voting_period"}},{"name":"juno_governance_deposit_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"juno","proposal_status":"deposit_period"}},{"name":"juno_governance_failed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"juno","proposal_status":"failed"}},{"name":"juno_governance_passed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"juno","proposal_status":"passed"}},{"name":"juno_governance_rejected_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"juno","proposal_status":"rejected"}},{"name":"cosmoshub_governance_voting_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"cosmoshub","proposal_status":"voting_period"}},{"name":"cosmoshub_governance_deposit_period_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"cosmoshub","proposal_status":"deposit_period"}},{"name":"cosmoshub_governance_failed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"cosmoshub","proposal_status":"failed"}},{"name":"cosmoshub_governance_passed_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"cosmoshub","proposal_status":"passed"}},{"name":"cosmoshub_governance_rejected_proposals","kind":"GovernanceProposals","refresh_rate":300,"args":{"blockchain":"cosmoshub","proposal_status":"rejected"}}]},{"name":"chain_registry","requirements":[{"name":"chain_registry","kind":"ChainRegistry","refresh_rate":600,"args":{"path":"./chain-registry"}}]},{"name":"fraud_detection","requirements":[{"name":"fraud_detection","kind":"FraudDetection","refresh_rate":60,"args":{}}]}] -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |

CRB - Cosmos Rust Bot™

5 |

A Rust Bot for the Cosmos Ecosystem.

6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | 16 | > :warning: No security audit has been performed. (*[See Disclaimer: Do your own research. Take a look at the code.](https://github.com/Philipp-Sc/cosmos-rust-bot/blob/0ecae398c80192822090598947ba7c0ee5cba562/DISCLAIMER.txt)*) 17 | 18 | ## 19 | 20 | ### [About](#about) · [Install](#install) · [Summary](#summary) 21 | 22 | ## About 23 | 24 | > Cosmos-Rust-Bot refers to this repository and it's code which enables others to build services on top of CRB. 25 | 26 | 27 | ### Description 28 | 29 | > Cosmos-Rust-Bot queries the blockchain nodes via **gRPC** (a remote procedure call protocol that uses protobufs for serializing structured data) for the best performance due to its binary encoding format. Also syncing directly to blockchain nodes using gRPC allows for efficient access to data and functionality, useful for tasks such as submitting transactions or querying the blockchain state. This avoids going through an additional layer of abstraction (e.g LCD/FCD). 30 | 31 | > Cosmos-Rust-Bot integrates **CosmWasm 1.0.0** via [cosmos-rust](https://github.com/cosmos/cosmos-rust) as well as providing its own adjustments (including additional types and osmosis-proto definitions) [here](https://github.com/Philipp-Sc/cosmos-rust-development). The resulting core is provided as simple rust crate [cosmos-rust-package](https://github.com/Philipp-Sc/cosmos-rust-package), making it easy to use in your own project. 32 | 33 | > Cosmos-Rust-Bot aims to be modular and therefore the following features/programs are integrated via **UNIX Sockets**, enabling them to be developed and updated sepearatly: [Fraud Detection](https://github.com/Philipp-Sc/rust-bert-fraud-detection), [LinkToText](https://github.com/Philipp-Sc/rust-link-to-text) and the [OpenAI API](https://github.com/Philipp-Sc/rust-openai-gpt-tools). 34 | 35 | > **Telegram** and **Signal Messenger** integrations are also available as separate package. 36 | 37 | > To bring everything together **Dockerfiles** are provided for easy setup and development. 38 | 39 | ## Install 40 | 41 | > dockerfiles available [here](https://github.com/Philipp-Sc/cosmos-rust-bot). 42 | 43 | # Services 44 | ## Cosmos Governance Briefings 45 | 46 | [@cosmos_governance_briefings_bot](https://t.me/cosmos_governance_briefings_bot) provides alerts and analysis on governance proposals, making it easier for users to navigate the process and stay informed about the proposals that are being considered. 47 | 48 | One of the unique features is the integrated fraud detection, which helps users identify potential scams or malicious proposals. This is particularly important in the cryptocurrency space, where scams and fraud can be a significant issue. I also use open source technology and AI to generate brief explanations of key aspects of governance proposals, helping users better understand technical language and make informed voting decisions. This is particularly useful for users who may be intimidated by the complexity or unfamiliar with the governance process, as it provides a more accessible and user-friendly way to participate. 49 | 50 | In addition to providing notifications and analysis, the bot also allows users to easily access and review proposals, staying up-to-date on the latest governance developments in the Cosmos ecosystem. This can be particularly helpful for users who may not have the time or resources to keep track of all the proposals on their own. 51 | 52 | ## Cosmos Governance Fraud Prevention 53 | 54 | Cosmos Governance Fraud Prevention is an API that offers spam, ham, and fraud classification for Cosmos Governance proposals. The API is hosted at [libreai.de/cosmos-governance-fraud-prevention/](libreai.de/cosmos-governance-fraud-prevention/), and it's designed to provide a trustworthiness evaluation of a proposal before voting. 55 | 56 | The API leverages cutting-edge machine learning algorithms to analyze proposal text and calculate a reputation score that indicates the probability of fraud or spam. 57 | 58 | How to use it: 59 | 60 | - fraud prediction > 0.4 indicating a moderate risk, provide a warning: 61 | - ```Stay safe. Be cautious..``` 62 | - fraud prediction >= 0.7 indicating a very high probability of a fraudulent activity, provide an alert: 63 | - ```Be cautious. Check URLs, avoid suspicious links, and remember, if it seems too good to be true, it probably is.``` 64 | 65 | 66 | 67 | This powerful tool is a significant step towards preventing bad actors from manipulating the Cosmos Governance process and ensuring transparent and fair decision-making. 68 | 69 | ## Summary 70 | 71 | > I created this bot to learn about smart contracts, the Terra blockchain and to get to know the Rust programming 72 | language. Post-attack the journey continues with a stronger focus on the broader Cosmos ecosystem. 73 | 74 | > Cosmos-rust-bot is a constant work in progress: **Bug Reports** and **Feature Requests** are welcome! 75 | 76 | > Thanks to the people who helped me along the way on the terra discord. :heart: 77 | 78 | > Special thanks to [PFC Validator](https://pfc-validator.github.io/) for being super helpful and providing their rust 79 | tooling open source. 80 | 81 | ## 82 | 83 | > Grant Recipient of 84 | the [Osmosis Grants Program](https://grants.osmosis.zone/) 85 | 86 | > Many thanks to the Osmosis Grants Team for incentivizing this project. :pray: 87 | 88 | ## License 89 | 90 | > Open Source 91 | > Apache-2.0 license 92 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-server/src/main.rs: -------------------------------------------------------------------------------- 1 | use actix_cors::Cors; 2 | use actix_web::{dev::ServiceRequest, get, App, Error, HttpServer, HttpResponse, web}; 3 | use actix_web_httpauth::extractors::basic::{BasicAuth}; 4 | use actix_web_httpauth::middleware::HttpAuthentication; 5 | use actix_web::middleware::Logger; 6 | 7 | use actix_web_httpauth::extractors::{AuthenticationError, bearer}; 8 | use actix_web_httpauth::headers::www_authenticate::basic::Basic; 9 | use actix_web::HttpRequest; 10 | 11 | use qstring::QString; 12 | use std::collections::hash_map::DefaultHasher; 13 | use std::hash::{Hash, Hasher}; 14 | 15 | use reqwest::Client; 16 | use reqwest::header::HeaderValue; 17 | use reqwest::header::CONTENT_TYPE; 18 | 19 | use actix_files::NamedFile; 20 | use actix_web::error::UrlGenerationError; 21 | use actix_web_httpauth::extractors::bearer::BearerAuth; 22 | use serde_json::json; 23 | 24 | 25 | use cosmos_rust_interface::utils::entry::*; 26 | use cosmos_rust_interface::utils::entry::db::query::socket::client_send_query_request; 27 | 28 | const QUERY_SOCKET: &str = "./tmp/cosmos_rust_bot_query_socket"; 29 | 30 | 31 | async fn validator( 32 | req: ServiceRequest, 33 | credentials: BasicAuth, 34 | ) -> Result { 35 | 36 | // Check if the request matches the file route 37 | let is_file_request = req.path().starts_with("/static/"); 38 | 39 | // If the request is a file request, skip the authentication check 40 | if is_file_request { 41 | Ok(req) 42 | }else { 43 | // For any other request the user needs to pass the authentication check 44 | if let (Some(Ok(token)), Ok(user_hash)) = (credentials.password().map(|pw| pw.parse::()), credentials.user_id().parse::()) { 45 | let request: UserQuery = UserQuery { 46 | query_part: QueryPart::AuthQueryPart(AuthQueryPart { token, user_hash }), 47 | settings_part: SettingsPart { 48 | subscribe: None, 49 | unsubscribe: None, 50 | register: None, 51 | user_hash: Some(user_hash) 52 | } 53 | }; 54 | 55 | if let Ok(CosmosRustServerValue::Notification(n)) = client_send_query_request(QUERY_SOCKET, request) { 56 | log::info!("Notification: {:?}", &n); 57 | 58 | let mut is_authorized = false; 59 | 60 | match n.query.query_part { 61 | QueryPart::AuthQueryPart(_) => { 62 | for i in 0..n.entries.len() { 63 | match &n.entries[i] { 64 | CosmosRustBotValue::Authorization(auth) => { 65 | is_authorized = auth.is_authorized; 66 | } 67 | _ => { 68 | is_authorized = false; 69 | } 70 | } 71 | break; 72 | } 73 | }, 74 | _ => { 75 | is_authorized = false; 76 | } 77 | } 78 | 79 | if is_authorized { 80 | return Ok(req); 81 | } 82 | } 83 | } 84 | Err((Error::from(AuthenticationError::new(Basic::default())), req)) 85 | } 86 | } 87 | 88 | 89 | async fn verify(_req: HttpRequest, _basic_auth: BasicAuth) -> actix_web::Result { 90 | Ok(HttpResponse::Ok().finish()) 91 | } 92 | 93 | async fn translate(_req: HttpRequest, info: web::Path<(String, String, String)>) -> actix_web::Result { 94 | let (lang, blockchain, id) = info.into_inner(); 95 | 96 | // where is the dirty work done? 97 | 98 | // Now I just need to ask Cosmos-Rust-Bot to fetch a translation. CRB may or may not need to query GPT. 99 | // On Okay, a json file is returned, that by then should now exist. 100 | 101 | Ok(HttpResponse::Ok().finish()) 102 | } 103 | 104 | 105 | /* 106 | #[get("/subscriptions")] 107 | async fn subscriptions(req: HttpRequest, bearer_auth: BearerAuth) -> actix_web::Result { 108 | 109 | // use auth token, to request 110 | 111 | let qs = QString::from(req.query_string()); 112 | if let Some(question_parameter) = (qs.get("question")) { 113 | 114 | } 115 | Ok(NamedFile::open("dummy.png")?) 116 | } 117 | 118 | #[get("/static/{filename:.+\\.json}")] 119 | async fn file_exists(req: HttpRequest) -> actix_web::Result { 120 | let filename = req.match_info().query("filename"); 121 | let file_path = format!("./static/{}", filename); 122 | NamedFile::open(&file_path)?; 123 | 124 | let response_body = json!({ 125 | "success": true, 126 | "message": "File retrieved successfully", 127 | "filename": filename 128 | }); 129 | 130 | Ok(HttpResponse::Ok() 131 | .content_type("application/json") 132 | .json(response_body)) 133 | } 134 | */ 135 | 136 | async fn file(req: HttpRequest) -> actix_web::Result { 137 | let filepath = req.match_info().query("filepath"); 138 | let ext = req.match_info().query("ext"); 139 | 140 | // Check if the file extension is allowed 141 | if ext == "json" || ext == "html" { 142 | Ok(NamedFile::open(format!("./tmp/public/{}.{}", filepath, ext))?) 143 | } else { 144 | Err(UrlGenerationError::ResourceNotFound.into()) 145 | } 146 | } 147 | 148 | #[actix_web::main] 149 | async fn main() -> std::io::Result<()> { 150 | HttpServer::new(move || { 151 | let auth = HttpAuthentication::basic(validator); 152 | App::new() 153 | //.wrap(auth) // to enable auth for all services 154 | .wrap(Cors::permissive()) 155 | .service( 156 | web::resource("/verify") 157 | .wrap(auth.clone()) 158 | .route(web::get().to(verify)), 159 | ) 160 | .service( 161 | web::resource("/translate/{lang}/{blockchain}/{id}") 162 | //.wrap(auth) 163 | .route(web::get().to(translate)), 164 | ) 165 | .service( 166 | web::resource("/static/{filepath:.*}.{ext:html|json}") 167 | //.wrap(auth) 168 | .route(web::get().to(file)), 169 | ) 170 | }) 171 | .bind(("0.0.0.0", 8081))? 172 | .run() 173 | .await 174 | } 175 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cosmos-rust-bot 2 | [A Rust Bot for the Cosmos Ecosystem.](https://github.com/Philipp-Sc/cosmos-rust-bot/tree/development/workspace/cosmos-rust-bot) 3 | 4 | ``` 5 | [rust-bert-fraud-detection, rust-link-to-text, rust-openai-gpt3-tools] <-----> FS 6 | | 7 | cosmos-rust-bot <-----> FS 8 | | \ 9 | | cosmos-rust-telegram-bot <-----> FS 10 | | | 11 | | END USER 12 | | | 13 | | | 14 | | nginx-reverse-proxy 15 | | / \ 16 | | / \ 17 | cosmos-rust-server file-server (miniserve) ---> FS 18 | ``` 19 | # Workspace Setup 20 | 21 | ```bash 22 | git clone https://github.com/Philipp-Sc/cosmos-rust-bot.git 23 | cd cosmos-rust-bot; 24 | export ROOT="$(pwd)" 25 | git submodule update --init 26 | ``` 27 | # Update Workspace 28 | 29 | ```bash 30 | git pull 31 | git submodule update --remote --rebase 32 | ``` 33 | ```bash 34 | # fix in case HEAD is detached 35 | git checkout main 36 | git submodule update --remote --rebase 37 | ``` 38 | # Docker 39 | 40 | > Docker is not required, but it helps a lot to efficiently development and maintaining the package. Take a look at the dockerfiles to figure out how to build and run the packages directly without docker. 41 | 42 | 43 | ## Build 44 | 45 | ### Build FRAUD DETECTION Service 46 | ```bash 47 | cd $ROOT/workspace/rust-bert-fraud-detection 48 | docker build -t rust-bert-fraud-detection . 49 | ``` 50 | 51 | ### Build GPT3 Service 52 | ```bash 53 | cd $ROOT/workspace/rust-openai-gpt3-tools 54 | docker build -t rust-openai-gpt3-tools . 55 | ``` 56 | 57 | ### Build LinkToText Service 58 | ```bash 59 | cd $ROOT/workspace/rust-link-to-text 60 | docker build -t rust-link-to-text . 61 | ``` 62 | 63 | ### Build Miniserve (File-server) 64 | ```bash 65 | cd $ROOT/workspace/miniserve 66 | docker build -t miniserve -f Dockerfile_file_server . 67 | ``` 68 | 69 | ## Build Nginx Reverse Proxy 70 | ```bash 71 | cd $ROOT/workspace/nginx-reverse-proxy 72 | docker build -t nginx_cors -f Dockerfile_nginx_cors . 73 | ``` 74 | 75 | ### Build Cosmos-Rust-Bot 76 | ```bash 77 | cd $ROOT 78 | docker build -t crb_build -f Dockerfile_build . # skip if already done 79 | docker run -it --rm -v "$(pwd)/workspace":/usr/workspace -v "$(pwd)/cargo_home":/usr/cargo_home -v "$(pwd)/target":/usr/target crb_build dev 80 | ``` 81 | ### Build Telegram Bot 82 | ```bash 83 | cd $ROOT 84 | docker build -t crb_build -f Dockerfile_build . # skip if already done 85 | docker run -it --rm -v "$(pwd)/workspace":/usr/workspace -v "$(pwd)/cargo_home":/usr/cargo_home -v "$(pwd)/target":/usr/target crb_build tg-bot 86 | ``` 87 | 88 | ### Build API (Cosmos-Rust-Server) 89 | ```bash 90 | cd $ROOT 91 | docker build -t crb_build -f Dockerfile_build . # skip if already done 92 | docker run -it --rm -v "$(pwd)/workspace":/usr/workspace -v "$(pwd)/cargo_home":/usr/cargo_home -v "$(pwd)/target":/usr/target crb_build api 93 | ``` 94 | 95 | 96 | ### Documentation 97 | ```bash 98 | ## the compiled package (binary) will be saved into the ./target directory. 99 | ## $ROOT/target/{debug,release}/* 100 | ``` 101 | 102 | ## Prepare 103 | 104 | ### Create Features File 105 | ```bash 106 | docker build -t crb_build -f Dockerfile_build . # skip if already done 107 | mkdir $ROOT/workspace/cosmos-rust-bot/tmp 108 | docker run -it --rm -v "$(pwd)/workspace":/usr/workspace -v "$(pwd)/cargo_home":/usr/cargo_home -v "$(pwd)/target":/usr/target crb_build test 109 | mv workspace/cosmos-rust-bot/tmp/cosmos-rust-bot-feature-list.json ./tmp/ 110 | ``` 111 | 112 | ## Run 113 | 114 | > It is recommended to start the services in this order. 115 | 116 | ### START FRAUD DETECTION Service 117 | ```bash 118 | cd $ROOT/workspace/rust-bert-fraud-detection 119 | docker run -d --rm -v "$(pwd)/rustbert_cache":/usr/rustbert_cache -v "$(pwd)/target":/usr/target -v "$(pwd)/cargo_home":/usr/cargo_home -v "$(pwd)/package":/usr/workspace -v "$(pwd)/../../tmp":/usr/workspace/tmp -v "$(pwd)/socket_ipc":/usr/socket_ipc rust-bert-fraud-detection cargo run --release start_service 120 | ``` 121 | ### START GPT3 Service 122 | ```bash 123 | cd $ROOT/workspace/rust-openai-gpt3-tools 124 | docker run -d --rm -v "$(pwd)/rustbert_cache":/usr/rustbert_cache -v "$(pwd)/target":/usr/target -v "$(pwd)/cargo_home":/usr/cargo_home -v "$(pwd)/package":/usr/workspace -v "$(pwd)/../../tmp":/usr/workspace/tmp -v "$(pwd)/socket_ipc":/usr/socket_ipc -e OPENAI_API_KEY=12345 rust-openai-gpt-tools cargo run --release start_service 125 | ``` 126 | ### START LinkToText Service 127 | ```bash 128 | cd $ROOT/workspace/rust-link-to-text 129 | docker run -d --rm -v "$(pwd)/target":/usr/target -v "$(pwd)/cargo_home":/usr/cargo_home -v "$(pwd)/package":/usr/workspace -v "$(pwd)/../../tmp":/usr/workspace/tmp -v "$(pwd)/socket_ipc":/usr/socket_ipc rust-link-to-text cargo run --release start_service 130 | ``` 131 | 132 | ### Start Miniserve 133 | ```bash 134 | cd $ROOT/workspace/miniserve 135 | docker run -d --rm -p 8080:8080 -v "$(pwd)/../../tmp/fraud_detection":/usr/workspace/public/cosmos-governance-fraud-prevention -v "$(pwd)/../../tmp/governance_proposals":/usr/workspace/public/cosmos-governance-proposals -v "$(pwd)/../../tmp/public":/usr/workspace/public/public miniserve miniserve ./public --hide-theme-selector --color-scheme-dark archlinux 136 | ``` 137 | 138 | ### Start Nginx Reverse Proxy 139 | ```bash 140 | cd $ROOT/workspace/nginx-reverse-proxy 141 | docker run -d --rm --name nginx_cors -p 443:443 -p 444:444 nginx_cors 142 | ``` 143 | 144 | ### START CosmosRustBot 145 | ```bash 146 | cd $ROOT 147 | docker build -t crb_run -f Dockerfile_run . # skip if already done 148 | docker run -d --rm -v "$(pwd)/target":/usr/target:ro -v "$(pwd)/tmp":/usr/workspace/tmp -v "$(pwd)/workspace/chain-registry":/usr/workspace/chain-registry -e RUST_LOG=Error crb_run dev 149 | ``` 150 | ### START Telegram Bot 151 | ```bash 152 | cd $ROOT 153 | docker build -t crb_run -f Dockerfile_run . # skip if already done 154 | docker run -d --rm -v "$(pwd)/target":/usr/target:ro -v "$(pwd)/tmp":/usr/workspace/tmp -e TELOXIDE_TOKEN=12345 crb_run tg-bot 155 | ``` 156 | 157 | ### START API 158 | ```bash 159 | cd $ROOT 160 | docker build -t crb_run -f Dockerfile_run . # skip if already done 161 | docker run -d --rm -v "$(pwd)/target":/usr/target:ro -v "$(pwd)/tmp":/usr/workspace/tmp -p 444:444 crb_run api 162 | ``` 163 | 164 | 165 | ### Documentation 166 | ```bash 167 | # (ICP is archived via sockets that are linked between docker containers via: -v "$(pwd)/tmp":/usr/workspace/tmp) 168 | ``` 169 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/src/model/requirements/mod.rs: -------------------------------------------------------------------------------- 1 | use bot_library::shared::UserSettings as UserSettingsImported; 2 | use serde::{Deserialize, Serialize}; 3 | use serde_json::json; 4 | use std::collections::HashMap; 5 | use std::fs; 6 | 7 | use lazy_static::lazy_static; 8 | 9 | const TASKS_PATH: &str = "./tmp/cosmos-rust-bot-feature-list.json"; 10 | 11 | pub type UserSettings = UserSettingsImported; 12 | 13 | // around every 5s a new block is generated 14 | 15 | const MINUTES_1: i32 = 60 * 1; 16 | const MINUTES_5: i32 = 60 * 5; 17 | const MINUTES_10: i32 = 60 * 10; 18 | 19 | const PROPOSAL_STATUS_LIST: [&str;5] = [ 20 | "voting_period", 21 | "deposit_period", 22 | "failed", 23 | "passed", 24 | "rejected", 25 | /*"nil",*/ // TODO query only if no other states of that proposal exist. 26 | ]; 27 | 28 | const PARAM_TYPES: [&str; 3] = [ 29 | "voting", 30 | "tallying", 31 | "deposit", 32 | ]; 33 | 34 | lazy_static! { 35 | static ref LIST_BLOCKCHAINS: Vec = { 36 | let data = std::fs::read_to_string("./tmp/supported_blockchains.json").expect("Unable to read file"); 37 | let supported_blockchains: HashMap = serde_json::from_str(&data).expect("Unable to parse JSON"); 38 | supported_blockchains.into_keys().collect() 39 | }; 40 | } 41 | 42 | #[derive(Debug, Serialize, Deserialize,PartialEq)] 43 | pub enum TaskType { 44 | ChainRegistry, 45 | FraudDetection, 46 | GPT3, 47 | LinkToText, 48 | GovernanceProposals, 49 | TallyResults, 50 | Params, 51 | Pool, 52 | None, 53 | } 54 | 55 | #[derive(Debug, Serialize, Deserialize)] 56 | pub struct Feature { 57 | name: String, 58 | requirements: Vec, 59 | } 60 | 61 | #[derive(Debug, Serialize, Deserialize)] 62 | pub struct TaskSpec { 63 | pub name: String, 64 | pub kind: TaskType, 65 | pub refresh_rate: i32, 66 | pub args: serde_json::Value, 67 | } 68 | 69 | pub fn feature_list() -> Vec { 70 | let feature_list: Vec = match fs::read_to_string(TASKS_PATH) 71 | { 72 | Ok(file) => match serde_json::from_str(&file) { 73 | Ok(res) => res, 74 | Err(err) => { 75 | println!("{:?}", err); 76 | Default::default() 77 | } 78 | }, 79 | Err(err) => { 80 | println!("{:?}", err); 81 | Default::default() 82 | } 83 | }; 84 | feature_list 85 | } 86 | 87 | pub fn feature_list_to_file() -> anyhow::Result<()> { 88 | let mut feature_list: Vec = Vec::new(); 89 | 90 | let mut governance_proposals: Vec = Vec::new(); 91 | let mut tally_results: Vec = Vec::new(); 92 | let mut params: Vec = Vec::new(); 93 | let mut pool: Vec = Vec::new(); 94 | 95 | for blockchain in LIST_BLOCKCHAINS.iter() { 96 | for params_type in &PARAM_TYPES { 97 | let task = TaskSpec { 98 | kind: TaskType::Params, 99 | name: format!("{}_params_{}", blockchain, params_type), 100 | args: json!({ 101 | "blockchain": blockchain, 102 | "params_type": params_type 103 | }), 104 | refresh_rate: MINUTES_10, 105 | }; 106 | params.push(task); 107 | } 108 | let task = TaskSpec { 109 | kind: TaskType::Pool, 110 | name: format!("pool_{}", blockchain), 111 | args: json!({ 112 | "blockchain": blockchain, 113 | }), 114 | refresh_rate: MINUTES_10, 115 | }; 116 | pool.push(task); 117 | let task = TaskSpec { 118 | kind: TaskType::TallyResults, 119 | name: format!("{}_tally_results_{}_proposals", blockchain, "voting_period"), 120 | args: json!({ 121 | "blockchain": blockchain, 122 | "proposal_status": "voting_period" 123 | }), 124 | refresh_rate: MINUTES_10, 125 | }; 126 | tally_results.push(task); 127 | for proposal_status in &PROPOSAL_STATUS_LIST { 128 | let task = TaskSpec { 129 | kind: TaskType::GovernanceProposals, 130 | name: format!("{}_governance_{}_proposals", blockchain, proposal_status), 131 | args: json!({ 132 | "blockchain": blockchain, 133 | "proposal_status": proposal_status 134 | }), 135 | refresh_rate: MINUTES_5, 136 | }; 137 | governance_proposals.push(task); 138 | } 139 | } 140 | 141 | feature_list.push(Feature { 142 | name: "governance_proposal_notifications".to_string(), 143 | requirements: governance_proposals, 144 | }); 145 | feature_list.push(Feature { 146 | name: "governance_proposal_tally_results".to_string(), 147 | requirements: tally_results, 148 | }); 149 | feature_list.push(Feature { 150 | name: "governance_proposal_pool".to_string(), 151 | requirements: pool, 152 | }); 153 | feature_list.push(Feature { 154 | name: "governance_proposal_params".to_string(), 155 | requirements: params, 156 | }); 157 | 158 | let mut chain_registry: Vec = Vec::new(); 159 | let task = TaskSpec { 160 | kind: TaskType::ChainRegistry, 161 | name: format!("chain_registry"), 162 | args: json!({ 163 | "path": "./chain-registry", 164 | }), 165 | refresh_rate: MINUTES_10, 166 | }; 167 | chain_registry.push(task); 168 | 169 | feature_list.push(Feature { 170 | name: "chain_registry".to_string(), 171 | requirements: chain_registry, 172 | }); 173 | 174 | let mut fraud_detection: Vec = Vec::new(); 175 | let task = TaskSpec { 176 | kind: TaskType::FraudDetection, 177 | name: format!("fraud_detection"), 178 | args: json!({ 179 | // here should be the socket path 180 | }), 181 | refresh_rate: 10, 182 | }; 183 | fraud_detection.push(task); 184 | 185 | feature_list.push(Feature { 186 | name: "fraud_detection".to_string(), 187 | requirements: fraud_detection, 188 | }); 189 | 190 | let mut gpt3: Vec = Vec::new(); 191 | let task = TaskSpec { 192 | kind: TaskType::GPT3, 193 | name: format!("gpt3"), 194 | args: json!({ 195 | // here should be the socket path 196 | }), 197 | refresh_rate: 10, 198 | }; 199 | gpt3.push(task); 200 | 201 | let mut link_to_text: Vec = Vec::new(); 202 | let task = TaskSpec { 203 | kind: TaskType::LinkToText, 204 | name: format!("link_to_text"), 205 | args: json!({ 206 | // here should be the socket path 207 | }), 208 | refresh_rate: 10, 209 | }; 210 | gpt3.push(task); 211 | 212 | feature_list.push(Feature { 213 | name: "gpt3".to_string(), 214 | requirements: gpt3, 215 | }); 216 | 217 | // TODO: create new feature task that gets all wallet info. 218 | 219 | let line = format!("{}", serde_json::to_string(&feature_list).unwrap()); 220 | fs::write(TASKS_PATH, &line).unwrap(); 221 | Ok(()) 222 | } 223 | 224 | fn feature_name_list(user_settings: &UserSettings) -> Vec { 225 | let mut args: Vec = Vec::new(); 226 | if user_settings.governance_proposal_notifications { 227 | args.push("governance_proposal_notifications".to_string()); 228 | args.push("governance_proposal_tally_results".to_string()); 229 | args.push("governance_proposal_pool".to_string()); 230 | args.push("governance_proposal_params".to_string()); 231 | } 232 | args.push("chain_registry".to_string()); 233 | args.push("fraud_detection".to_string()); 234 | args.push("gpt3".to_string()); 235 | args 236 | } 237 | 238 | pub fn get_feature_list(user_settings: &UserSettings) -> Vec { 239 | let args = feature_name_list(user_settings); 240 | let mut features = feature_list(); 241 | features = features 242 | .into_iter() 243 | .filter(|x| args.contains(&x.name)) 244 | .collect(); 245 | features 246 | } 247 | 248 | pub fn get_requirements(user_settings: &UserSettings) -> Vec { 249 | let mut features: Vec = get_feature_list(user_settings); 250 | let mut req: Vec = Vec::new(); 251 | for mut f in features { 252 | let mut no_duplicates = f 253 | .requirements 254 | .into_iter() 255 | .filter(|x| req.iter().filter(|y| y.name == x.name).count() == 0) 256 | .collect(); 257 | req.append(&mut no_duplicates); 258 | } 259 | req 260 | } 261 | 262 | #[cfg(test)] 263 | mod test { 264 | 265 | use cosmos_rust_interface::cosmos_rust_package::tokio as tokio; 266 | // cargo test -- --nocapture 267 | 268 | #[tokio::test] 269 | pub async fn feature_list_to_file() -> anyhow::Result<()> { 270 | super::feature_list_to_file() 271 | } 272 | 273 | #[tokio::test] 274 | pub async fn feature_list() -> anyhow::Result<()> { 275 | println!("{:?}", super::feature_list()); 276 | Ok(()) 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate litcrypt; 3 | //https://github.com/anvie/litcrypt.rs 4 | use_litcrypt!(); 5 | 6 | use bot_library::shared::{get_input, load_user_settings}; 7 | 8 | mod account; 9 | //mod control; 10 | mod model; 11 | 12 | use account::wallet::{decrypt_text_with_secret, encrypt_text_with_secret}; 13 | //use control::try_run_function; 14 | use model::requirements::UserSettings; 15 | 16 | use cosmos_rust_interface::cosmos_rust_package::chrono::Utc; 17 | use core::future::Future; 18 | use core::pin::Pin; 19 | use secstr::*; 20 | use std::collections::HashMap; 21 | use std::fs; 22 | use std::sync::Arc; 23 | use std::time::Duration; 24 | use cosmos_rust_interface::cosmos_rust_package::tokio as tokio; 25 | use tokio::sync::{Mutex, RwLock}; 26 | use tokio::task::JoinSet; 27 | 28 | use notify::{watcher, RecursiveMode, Watcher}; 29 | use std::sync::mpsc::channel; 30 | 31 | use cosmos_rust_interface::blockchain::account_from_seed_phrase; 32 | use std::collections::hash_map::DefaultHasher; 33 | use std::hash::{Hash, Hasher}; 34 | use std::{thread, time}; 35 | 36 | use cosmos_rust_interface::utils::entry::db::load_sled_db; 37 | use cosmos_rust_interface::utils::entry::db::query::socket::spawn_socket_query_server; 38 | use cosmos_rust_interface::utils::entry::postproc::blockchain::cosmos::gov::governance_proposal_notifications; 39 | use cosmos_rust_interface::utils::entry::postproc::meta_data::debug::debug; 40 | use cosmos_rust_interface::utils::entry::postproc::meta_data::errors::errors; 41 | //use cosmos_rust_interface::utils::entry::postproc::meta_data::logs::logs; 42 | use cosmos_rust_interface::utils::entry::*; 43 | use cosmos_rust_interface::utils::response::ResponseResult; 44 | use cosmos_rust_interface::cosmos_rust_package::api::core::cosmos::channels; 45 | 46 | use cosmos_rust_interface::cosmos_rust_package::api::core::cosmos::channels::SupportedBlockchain; 47 | use crate::model::{get_task_meta_data, poll_resolved_tasks, try_spawn_upcoming_tasks}; 48 | use crate::model::requirements::get_requirements; 49 | 50 | use cosmos_rust_interface::utils::entry::db::*; 51 | use cosmos_rust_interface::utils::entry::db::query::CosmosRustBotStoreInquirer; 52 | 53 | const QUERY_SOCKET: &str = "./tmp/cosmos_rust_bot_query_socket"; 54 | const SETTINGS_PATH: &str = "./tmp/cosmos-rust-bot.json"; 55 | const CRB_SLED_DB: &str = "./tmp/cosmos_rust_bot_sled_db"; 56 | const TASK_STORE_SLED_DB: &str = "./tmp/task_store_sled_db"; 57 | const CRB_SUBSCRIPTION_STORE_SLED_DB: &str = "./tmp/cosmos_rust_bot_subscriptions_sled_db"; 58 | const CRB_SUBSCRIPTION_STORE_JSON: &str = "./tmp/cosmos_rust_bot_subscriptions.json"; 59 | const CRB_REGISTRATION_STORE_JSON: &str = "./tmp/cosmos_rust_bot_registrations.json"; 60 | 61 | 62 | #[tokio::main] 63 | async fn main() -> anyhow::Result<()> { 64 | 65 | env_logger::init(); 66 | 67 | // TODO: supported blockchains need to be managed in a central manner. 68 | // to apply certain limitations. 69 | // there should be a Mutex such that each endpoint can only be used for one request at a time. 70 | 71 | 72 | // stores all requirements either as task or the resolved value. 73 | let mut join_set: JoinSet<()> = JoinSet::new(); 74 | let task_store: TaskMemoryStore = TaskMemoryStore::new(Some(TASK_STORE_SLED_DB.to_string())).unwrap(); 75 | 76 | let mut user_settings: UserSettings = load_user_settings(SETTINGS_PATH); 77 | //println!("{}", serde_json::to_string_pretty(&user_settings)?); 78 | 79 | let (wallet_seed_phrase, wallet_acc_address) = get_wallet_details(&user_settings).await; 80 | 81 | // Create a channel to receive the events. 82 | let (tx, rx) = channel(); 83 | // Create a watcher object, delivering debounced events. 84 | // The notification back-end is selected based on the platform. 85 | let mut watcher = watcher(tx, Duration::from_secs(10)).unwrap(); 86 | // Add a path to be watched. All files and directories at that path and 87 | // below will be monitored for changes. 88 | watcher 89 | .watch(SETTINGS_PATH, RecursiveMode::Recursive) 90 | .unwrap(); 91 | 92 | let entry_index_db = load_sled_db(CRB_SLED_DB); 93 | let subscription_db = load_sled_db(CRB_SUBSCRIPTION_STORE_SLED_DB); 94 | let subscription_store = SubscriptionStore::new(&subscription_db); 95 | subscription_store.import_subscriptions(CRB_SUBSCRIPTION_STORE_JSON); 96 | subscription_store.import_registrations(CRB_REGISTRATION_STORE_JSON); 97 | 98 | let mut cosmos_rust_bot_store = CosmosRustBotStore::new(entry_index_db,subscription_store); 99 | 100 | spawn_socket_query_server(QUERY_SOCKET,&cosmos_rust_bot_store); 101 | 102 | let _thread = cosmos_rust_bot_store.spawn_notify_on_subscription_update_task(); 103 | 104 | loop { 105 | let req = get_requirements(&user_settings); 106 | 107 | while !user_settings.pause_requested { 108 | if user_settings.hot_reload { 109 | match rx.recv_timeout(Duration::from_millis(10)) { 110 | Ok(event) => { 111 | println!("{:?}", event); 112 | break; 113 | } 114 | Err(_e) => { 115 | //println!("watch error: {:?}", e), 116 | } 117 | } 118 | } 119 | 120 | let number_of_tasks_resolved = poll_resolved_tasks(&mut join_set).await; 121 | 122 | let _number_of_tasks_added = try_spawn_upcoming_tasks( 123 | &mut join_set, 124 | &task_store, 125 | &req, 126 | &user_settings, 127 | &wallet_acc_address 128 | ).await; 129 | 130 | if number_of_tasks_resolved > 0 { 131 | 132 | // TODO: use SledDb listener/events to reduce the number of get function calls. 133 | // TODO: have dependencies and update trigger key lists. if trigger key was updated, then get dependencies and update. 134 | 135 | let mut entries: Vec = Vec::new(); 136 | 137 | let mut task_meta_data: Vec = get_task_meta_data(&task_store, &req).await; 138 | entries.append(&mut task_meta_data); 139 | 140 | if user_settings.governance_proposal_notifications { 141 | entries.append(&mut governance_proposal_notifications(&task_store)); 142 | } 143 | 144 | let mut task_meta_data: Vec = Vec::new(); 145 | //let mut debug: Vec = debug(&mut internal_snapshot_of_memory); 146 | //let mut logs: Vec = logs(&snapshot_of_memory); 147 | let mut errors: Vec = errors(&task_store); // TODO: make debug, errors, logs one. 148 | //task_meta_data.append(&mut debug); 149 | //task_meta_data.append(&mut logs); 150 | task_meta_data.append(&mut errors); 151 | entries.append(&mut task_meta_data); 152 | 153 | CosmosRustBotValue::add_index(&mut entries, "timestamp", "timestamp"); 154 | 155 | cosmos_rust_bot_store.update_items(entries); 156 | } else { 157 | let millis = time::Duration::from_millis(500); 158 | thread::sleep(millis); 159 | } 160 | } 161 | join_set.shutdown().await; 162 | if user_settings.hot_reload { 163 | user_settings = load_user_settings(SETTINGS_PATH); 164 | } 165 | } 166 | } 167 | 168 | async fn get_wallet_details(user_settings: &UserSettings) -> (Arc, Arc) { 169 | /* Get wallet details */ 170 | let mut wallet_seed_phrase = SecUtf8::from("".to_string()); 171 | let mut wallet_acc_address = SecUtf8::from( 172 | user_settings 173 | .terra_wallet_address 174 | .as_ref() 175 | .unwrap_or(&"".to_string()), 176 | ); 177 | // /^terra1[a-z0-9]{38}$/] 178 | 179 | if false 180 | /*user_settings.anchor_protocol_auto_repay || user_settings.anchor_protocol_auto_borrow || user_settings.anchor_protocol_auto_stake || user_settings.anchor_protocol_auto_farm*/ 181 | { 182 | // ** seed phrase needed ** 183 | wallet_seed_phrase = encrypt_text_with_secret( 184 | get_input("Enter your seed phrase (press Enter to skip):").to_string(), 185 | ); 186 | if wallet_acc_address.unsecure().len() != 44 || !user_settings.test { 187 | wallet_acc_address = SecUtf8::from( 188 | account_from_seed_phrase( 189 | decrypt_text_with_secret(&wallet_seed_phrase), 190 | channels::get_supported_blockchains_from_chain_registry("./chain-registry".to_string(),true,None) 191 | .await.get("terra2") 192 | .unwrap() 193 | .clone(), 194 | ) 195 | .unwrap_or("".to_string()), 196 | ); 197 | } 198 | } else if wallet_acc_address.unsecure().len() == 0 { 199 | // ** maybe need wallet address ** 200 | if false 201 | /*user_settings.anchor_account_info || user_settings.anchor_protocol_auto_repay || user_settings.anchor_protocol_auto_borrow || user_settings.anchor_protocol_auto_stake || user_settings.anchor_protocol_auto_farm*/ 202 | { 203 | wallet_acc_address = SecUtf8::from( 204 | get_input("Enter your wallet address (press Enter to skip):").to_string(), 205 | ); 206 | } 207 | } 208 | println!("{esc}c", esc = 27 as char); 209 | 210 | // Arc allows multiple references to the same object, 211 | // to potentially spawn multiple tasks with access to the seed phrase, while not revealing the string. 212 | let wallet_seed_phrase = Arc::new(wallet_seed_phrase); 213 | let wallet_acc_address = Arc::new(wallet_acc_address); 214 | (wallet_seed_phrase, wallet_acc_address) 215 | } 216 | -------------------------------------------------------------------------------- /workspace/cosmos-rust-bot/packages/cosmos-rust-signal-bot/src/cosmos_rust_bot/mod.rs: -------------------------------------------------------------------------------- 1 | use chrono::Utc; 2 | use cosmos_rust_interface::utils::entry::{ 3 | db::{notification::notify_sled_db, query::socket::*}, 4 | CosmosRustServerValue, Notify, 5 | }; 6 | use regex::Regex; 7 | 8 | use heck::ToTitleCase; 9 | use std::collections::HashMap; 10 | 11 | pub async fn handle_message(msg: String, db: &sled::Db) { 12 | let msg = msg.to_lowercase(); 13 | 14 | let blockchain_regex = "(terra2|osmosis|juno)"; 15 | let state_regex = "(pending|resolved|upcoming|failed|unknown|reserved)"; 16 | let sub_regex = "(subscribe|unsubscribe)"; 17 | let task_info_regex = Regex::new( 18 | format!( 19 | "task (count|list|history)(?: {})?(?: ([0-9]+))?(?: {})?(?:\\s|$)", 20 | state_regex, sub_regex 21 | ) 22 | .as_str(), 23 | ) 24 | .unwrap(); 25 | let lookup_proposals_regex = Regex::new(format!("proposals(?: {})?(?: #([0-9]+))?(?: (nil|passed|failed|rejected|deposit period|voting period))?(?: (text|community pool spend|parameter change|software upgrade|client update|update pool incentives|store code|unknown))?(?: (latest|submit|deposit end|voting start|voting end))?(?: ([0-9]+))?(?: {})?(?:\\s|$)", blockchain_regex, sub_regex).as_str()).unwrap(); 26 | let log_error_debug_regex = Regex::new( 27 | format!( 28 | "results (logs|errors|debug)(?: ([0-9]+))?(?: {})?(?:\\s|$)", 29 | sub_regex 30 | ) 31 | .as_str(), 32 | ) 33 | .unwrap(); 34 | let help_regex = Regex::new("help(?:\\s|$)").unwrap(); 35 | let help_examples_regex = Regex::new("help examples(?:\\s|$)").unwrap(); 36 | let mut request = serde_json::Value::Null; 37 | 38 | if help_examples_regex.is_match(&msg) { 39 | notify_sled_db( 40 | db, 41 | CosmosRustServerValue::Notify(Notify { 42 | timestamp: Utc::now().timestamp(), 43 | msg: vec![ 44 | r#"🔭 Monitor Tasks🔭 45 | ================= 46 | 🤖 EXAMPLES 47 | task count 48 | task count resolved 49 | task count failed 50 | task list 51 | task history failed subscribe"# 52 | .to_string(), 53 | r#"🔭 Monitor Results🔭 54 | ================== 55 | 🤖 EXAMPLES 56 | results logs 57 | results errors subscribe 58 | results errors 1"# 59 | .to_string(), 60 | r#"🛰️ Lookup Governance Proposals 🛰️ 61 | =============================== 62 | 🤖 EXAMPLES 63 | governance proposals osmosis #1 64 | governance proposals osmosis 3 65 | governance proposals terra2 voting period subscribe 66 | governance proposals juno rejected 5"# 67 | .to_string(), 68 | ], 69 | }), 70 | ); 71 | } else if help_regex.is_match(&msg) { 72 | notify_sled_db( 73 | db, 74 | CosmosRustServerValue::Notify(Notify { 75 | timestamp: Utc::now().timestamp(), 76 | msg: vec![r#"💫 Help 77 | ======= 78 | 🤖 COMMAND 79 | help 80 | 📣 SUBCOMMAND 81 | ['examples']"#.to_string(), 82 | r#"🔭️ Monitor Tasks🔭 83 | ================= 84 | 🤖 COMMAND 85 | task