Retrieves social infos + post on Telegram
Some checks reported errors
continuous-integration/drone/push Build encountered an error

This commit is contained in:
Alexandre RAY-BERNAT 2025-04-24 14:04:56 +02:00
parent b4a6da9a81
commit 8cfd0370cc
8 changed files with 810 additions and 285 deletions

42
.drone.yml Normal file
View File

@ -0,0 +1,42 @@
kind: pipeline
type: kubernetes
name: build
platform:
os: linux
arch: amd64
dns_config:
options:
- name: ndots
value: "1"
steps:
- name: check & build
image: code.raybernat.com/tooling/drone-rust-plugin:latest
pull: always
commands:
- cargo build
- name: docker build & push
image: plugins/docker
environment:
PLUGIN_MTU: 1300
privileged: true
settings:
dockerfile: Dockerfile
repo: code.raybernat.com/alex/solana_scanner
registry: code.raybernat.com
tags:
- latest
- ${DRONE_COMMIT_SHA}
depends_on:
- "check & build"
when:
event:
- push
trigger:
event:
- pull_request
- push
branch:
- main

491
Cargo.lock generated
View File

@ -392,6 +392,12 @@ dependencies = [
"syn 2.0.100", "syn 2.0.100",
] ]
[[package]]
name = "atomic-waker"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]] [[package]]
name = "atty" name = "atty"
version = "0.2.14" version = "0.2.14"
@ -1201,6 +1207,16 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e"
dependencies = [
"libc",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "event-listener" name = "event-listener"
version = "2.5.3" version = "2.5.3"
@ -1228,6 +1244,12 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
] ]
[[package]]
name = "fastrand"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
[[package]] [[package]]
name = "feature-probe" name = "feature-probe"
version = "0.1.1" version = "0.1.1"
@ -1487,7 +1509,26 @@ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"futures-util", "futures-util",
"http", "http 0.2.12",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "h2"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633"
dependencies = [
"atomic-waker",
"bytes",
"fnv",
"futures-core",
"futures-sink",
"http 1.3.1",
"indexmap", "indexmap",
"slab", "slab",
"tokio", "tokio",
@ -1593,6 +1634,17 @@ dependencies = [
"itoa", "itoa",
] ]
[[package]]
name = "http"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]] [[package]]
name = "http-body" name = "http-body"
version = "0.4.6" version = "0.4.6"
@ -1600,7 +1652,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2"
dependencies = [ dependencies = [
"bytes", "bytes",
"http", "http 0.2.12",
"pin-project-lite",
]
[[package]]
name = "http-body"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
"http 1.3.1",
]
[[package]]
name = "http-body-util"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
dependencies = [
"bytes",
"futures-core",
"http 1.3.1",
"http-body 1.0.1",
"pin-project-lite", "pin-project-lite",
] ]
@ -1632,9 +1707,9 @@ dependencies = [
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2", "h2 0.3.26",
"http", "http 0.2.12",
"http-body", "http-body 0.4.6",
"httparse", "httparse",
"httpdate", "httpdate",
"itoa", "itoa",
@ -1646,6 +1721,26 @@ dependencies = [
"want", "want",
] ]
[[package]]
name = "hyper"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"h2 0.4.9",
"http 1.3.1",
"http-body 1.0.1",
"httparse",
"itoa",
"pin-project-lite",
"smallvec",
"tokio",
"want",
]
[[package]] [[package]]
name = "hyper-rustls" name = "hyper-rustls"
version = "0.24.2" version = "0.24.2"
@ -1653,11 +1748,64 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"http", "http 0.2.12",
"hyper", "hyper 0.14.32",
"rustls 0.21.12", "rustls 0.21.12",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls 0.24.1",
]
[[package]]
name = "hyper-rustls"
version = "0.27.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
dependencies = [
"futures-util",
"http 1.3.1",
"hyper 1.6.0",
"hyper-util",
"rustls 0.23.25",
"rustls-pki-types",
"tokio",
"tokio-rustls 0.26.2",
"tower-service",
]
[[package]]
name = "hyper-tls"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
dependencies = [
"bytes",
"http-body-util",
"hyper 1.6.0",
"hyper-util",
"native-tls",
"tokio",
"tokio-native-tls",
"tower-service",
]
[[package]]
name = "hyper-util"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"http 1.3.1",
"http-body 1.0.1",
"hyper 1.6.0",
"libc",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
] ]
[[package]] [[package]]
@ -2016,6 +2164,12 @@ dependencies = [
"libsecp256k1-core", "libsecp256k1-core",
] ]
[[package]]
name = "linux-raw-sys"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]] [[package]]
name = "litemap" name = "litemap"
version = "0.7.5" version = "0.7.5"
@ -2129,6 +2283,23 @@ dependencies = [
"thiserror 1.0.69", "thiserror 1.0.69",
] ]
[[package]]
name = "native-tls"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
dependencies = [
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework 2.11.1",
"security-framework-sys",
"tempfile",
]
[[package]] [[package]]
name = "nix" name = "nix"
version = "0.29.0" version = "0.29.0"
@ -2819,11 +2990,11 @@ dependencies = [
"encoding_rs", "encoding_rs",
"futures-core", "futures-core",
"futures-util", "futures-util",
"h2", "h2 0.3.26",
"http", "http 0.2.12",
"http-body", "http-body 0.4.6",
"hyper", "hyper 0.14.32",
"hyper-rustls", "hyper-rustls 0.24.2",
"ipnet", "ipnet",
"js-sys", "js-sys",
"log", "log",
@ -2833,14 +3004,14 @@ dependencies = [
"percent-encoding", "percent-encoding",
"pin-project-lite", "pin-project-lite",
"rustls 0.21.12", "rustls 0.21.12",
"rustls-pemfile", "rustls-pemfile 1.0.4",
"serde", "serde",
"serde_json", "serde_json",
"serde_urlencoded", "serde_urlencoded",
"sync_wrapper", "sync_wrapper 0.1.2",
"system-configuration", "system-configuration 0.5.1",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls 0.24.1",
"tokio-util", "tokio-util",
"tower-service", "tower-service",
"url", "url",
@ -2851,6 +3022,50 @@ dependencies = [
"winreg", "winreg",
] ]
[[package]]
name = "reqwest"
version = "0.12.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d19c46a6fdd48bc4dab94b6103fccc55d34c67cc0ad04653aad4ea2a07cd7bbb"
dependencies = [
"base64 0.22.1",
"bytes",
"encoding_rs",
"futures-core",
"futures-util",
"h2 0.4.9",
"http 1.3.1",
"http-body 1.0.1",
"http-body-util",
"hyper 1.6.0",
"hyper-rustls 0.27.5",
"hyper-tls",
"hyper-util",
"ipnet",
"js-sys",
"log",
"mime",
"native-tls",
"once_cell",
"percent-encoding",
"pin-project-lite",
"rustls-pemfile 2.2.0",
"serde",
"serde_json",
"serde_urlencoded",
"sync_wrapper 1.0.2",
"system-configuration 0.6.1",
"tokio",
"tokio-native-tls",
"tower",
"tower-service",
"url",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
"windows-registry",
]
[[package]] [[package]]
name = "reqwest-middleware" name = "reqwest-middleware"
version = "0.2.5" version = "0.2.5"
@ -2859,8 +3074,8 @@ checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"async-trait", "async-trait",
"http", "http 0.2.12",
"reqwest", "reqwest 0.11.27",
"serde", "serde",
"task-local-extensions", "task-local-extensions",
"thiserror 1.0.69", "thiserror 1.0.69",
@ -2910,6 +3125,19 @@ dependencies = [
"nom", "nom",
] ]
[[package]]
name = "rustix"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf"
dependencies = [
"bitflags 2.9.0",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.21.12" version = "0.21.12"
@ -2945,7 +3173,7 @@ dependencies = [
"openssl-probe", "openssl-probe",
"rustls-pki-types", "rustls-pki-types",
"schannel", "schannel",
"security-framework", "security-framework 3.2.0",
] ]
[[package]] [[package]]
@ -2957,6 +3185,15 @@ dependencies = [
"base64 0.21.7", "base64 0.21.7",
] ]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"rustls-pki-types",
]
[[package]] [[package]]
name = "rustls-pki-types" name = "rustls-pki-types"
version = "1.11.0" version = "1.11.0"
@ -2981,7 +3218,7 @@ dependencies = [
"rustls-native-certs", "rustls-native-certs",
"rustls-platform-verifier-android", "rustls-platform-verifier-android",
"rustls-webpki 0.103.1", "rustls-webpki 0.103.1",
"security-framework", "security-framework 3.2.0",
"security-framework-sys", "security-framework-sys",
"webpki-root-certs", "webpki-root-certs",
"windows-sys 0.59.0", "windows-sys 0.59.0",
@ -3060,6 +3297,19 @@ dependencies = [
"untrusted", "untrusted",
] ]
[[package]]
name = "security-framework"
version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.9.0",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "3.2.0" version = "3.2.0"
@ -3273,9 +3523,9 @@ checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.5.8" version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.52.0", "windows-sys 0.52.0",
@ -4091,7 +4341,7 @@ dependencies = [
"gethostname", "gethostname",
"lazy_static", "lazy_static",
"log", "log",
"reqwest", "reqwest 0.11.27",
"solana-clock", "solana-clock",
"solana-cluster-type", "solana-cluster-type",
"solana-sha256-hasher", "solana-sha256-hasher",
@ -4481,7 +4731,7 @@ dependencies = [
"crossbeam-channel", "crossbeam-channel",
"futures-util", "futures-util",
"log", "log",
"reqwest", "reqwest 0.11.27",
"semver", "semver",
"serde", "serde",
"serde_derive", "serde_derive",
@ -4623,7 +4873,7 @@ dependencies = [
"bs58", "bs58",
"indicatif", "indicatif",
"log", "log",
"reqwest", "reqwest 0.11.27",
"reqwest-middleware", "reqwest-middleware",
"semver", "semver",
"serde", "serde",
@ -4659,7 +4909,7 @@ dependencies = [
"base64 0.22.1", "base64 0.22.1",
"bs58", "bs58",
"jsonrpc-core", "jsonrpc-core",
"reqwest", "reqwest 0.11.27",
"reqwest-middleware", "reqwest-middleware",
"semver", "semver",
"serde", "serde",
@ -5502,6 +5752,7 @@ dependencies = [
"libc", "libc",
"log", "log",
"mpl-token-metadata", "mpl-token-metadata",
"reqwest 0.12.15",
"serde", "serde",
"serde_json", "serde_json",
"solana-account-decoder", "solana-account-decoder",
@ -5512,6 +5763,7 @@ dependencies = [
"solana-transaction-status", "solana-transaction-status",
"solana-transaction-status-client-types", "solana-transaction-status-client-types",
"spl-token 8.0.0", "spl-token 8.0.0",
"tokio",
] ]
[[package]] [[package]]
@ -5955,6 +6207,15 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "sync_wrapper"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
dependencies = [
"futures-core",
]
[[package]] [[package]]
name = "synstructure" name = "synstructure"
version = "0.12.6" version = "0.12.6"
@ -5986,7 +6247,18 @@ checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"core-foundation 0.9.4", "core-foundation 0.9.4",
"system-configuration-sys", "system-configuration-sys 0.5.0",
]
[[package]]
name = "system-configuration"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.9.0",
"core-foundation 0.9.4",
"system-configuration-sys 0.6.0",
] ]
[[package]] [[package]]
@ -5999,6 +6271,16 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "system-configuration-sys"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "task-local-extensions" name = "task-local-extensions"
version = "0.1.4" version = "0.1.4"
@ -6008,6 +6290,19 @@ dependencies = [
"pin-utils", "pin-utils",
] ]
[[package]]
name = "tempfile"
version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
dependencies = [
"fastrand",
"getrandom 0.3.2",
"once_cell",
"rustix",
"windows-sys 0.59.0",
]
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.4.1" version = "1.4.1"
@ -6142,6 +6437,16 @@ dependencies = [
"syn 2.0.100", "syn 2.0.100",
] ]
[[package]]
name = "tokio-native-tls"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
dependencies = [
"native-tls",
"tokio",
]
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.24.1" version = "0.24.1"
@ -6152,6 +6457,16 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "tokio-rustls"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
dependencies = [
"rustls 0.23.25",
"tokio",
]
[[package]] [[package]]
name = "tokio-stream" name = "tokio-stream"
version = "0.1.17" version = "0.1.17"
@ -6173,7 +6488,7 @@ dependencies = [
"log", "log",
"rustls 0.21.12", "rustls 0.21.12",
"tokio", "tokio",
"tokio-rustls", "tokio-rustls 0.24.1",
"tungstenite", "tungstenite",
"webpki-roots 0.25.4", "webpki-roots 0.25.4",
] ]
@ -6217,6 +6532,27 @@ dependencies = [
"winnow", "winnow",
] ]
[[package]]
name = "tower"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
dependencies = [
"futures-core",
"futures-util",
"pin-project-lite",
"sync_wrapper 1.0.2",
"tokio",
"tower-layer",
"tower-service",
]
[[package]]
name = "tower-layer"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.3" version = "0.3.3"
@ -6258,7 +6594,7 @@ dependencies = [
"byteorder", "byteorder",
"bytes", "bytes",
"data-encoding", "data-encoding",
"http", "http 0.2.12",
"httparse", "httparse",
"log", "log",
"rand 0.8.5", "rand 0.8.5",
@ -6583,6 +6919,35 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
[[package]]
name = "windows-registry"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3"
dependencies = [
"windows-result",
"windows-strings",
"windows-targets 0.53.0",
]
[[package]]
name = "windows-result"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
dependencies = [
"windows-link",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.45.0" version = "0.45.0"
@ -6658,13 +7023,29 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6", "windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6", "windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6", "windows_i686_gnu 0.52.6",
"windows_i686_gnullvm", "windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6", "windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6", "windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6", "windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6", "windows_x86_64_msvc 0.52.6",
] ]
[[package]]
name = "windows-targets"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
dependencies = [
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
"windows_i686_gnullvm 0.53.0",
"windows_i686_msvc 0.53.0",
"windows_x86_64_gnu 0.53.0",
"windows_x86_64_gnullvm 0.53.0",
"windows_x86_64_msvc 0.53.0",
]
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.42.2" version = "0.42.2"
@ -6683,6 +7064,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.42.2" version = "0.42.2"
@ -6701,6 +7088,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.42.2" version = "0.42.2"
@ -6719,12 +7112,24 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
[[package]] [[package]]
name = "windows_i686_gnullvm" name = "windows_i686_gnullvm"
version = "0.52.6" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.42.2" version = "0.42.2"
@ -6743,6 +7148,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.42.2" version = "0.42.2"
@ -6761,6 +7172,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.42.2" version = "0.42.2"
@ -6779,6 +7196,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
@ -6797,6 +7220,12 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.7.4" version = "0.7.4"

View File

@ -25,7 +25,8 @@ mpl-token-metadata = "5.1.0"
solana-program = "2.2.1" solana-program = "2.2.1"
serde_json = "1.0.140" serde_json = "1.0.140"
log = "0.4.27" log = "0.4.27"
reqwest = { version = "0.12.15", features = ["json"] }
tokio = { version = "1", features = ["full"] }
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
libc = "0.2" libc = "0.2"

View File

@ -43,20 +43,22 @@ pub struct UiParsedTokenAccount {
space: Option<u64>, space: Option<u64>,
} }
#[derive( Debug)]
pub struct Transaction { pub struct Transaction {
pub(crate) signature: String, pub(crate) signature: String,
pub(crate) slot: Slot, pub(crate) slot: Slot,
pub(crate) block_time: Option<i64>, pub(crate) block_time: Option<i64>,
pub(crate) status: Option<TransactionError>, pub(crate) status: Option<TransactionError>,
pub(crate) account_keys: AccountKeys pub(crate) account_keys: AccountKeys,
} }
#[derive(Debug)]
pub struct AccountKeys { pub struct AccountKeys {
pub(crate) payer: Pubkey, pub(crate) payer: Pubkey,
pub(crate) mint_account: Pubkey, pub(crate) mint_account: Pubkey,
pub(crate) rent_account: Pubkey, pub(crate) rent_account: Pubkey,
pub(crate) mint_authority: Pubkey, pub(crate) mint_authority: Pubkey,
pub(crate) token_program: Pubkey pub(crate) token_program: Pubkey,
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -68,5 +70,30 @@ pub struct TokenData {
pub(crate) dev_balance: f64, pub(crate) dev_balance: f64,
pub(crate) mint_authority: bool, pub(crate) mint_authority: bool,
pub(crate) freeze_authority: bool, pub(crate) freeze_authority: bool,
} }
#[derive(Debug, Deserialize)]
pub struct TokenSocials {
pub(crate) createdOn: String,
pub(crate) description: String,
pub(crate) image: String,
pub(crate) name: String,
pub(crate) symbol: String,
pub(crate) twitter: String,
pub(crate) website: String
}
impl Default for TokenSocials {
fn default() -> Self {
Self {
createdOn: "".to_string(),
description: "".to_string(),
image: "".to_string(),
name: "".to_string(),
symbol: "".to_string(),
twitter: "".to_string(),
website: "".to_string(),
}
}
}

View File

@ -1,9 +1,12 @@
use std::error::Error;
use bs58; use bs58;
use chrono; use chrono;
use solana_sdk::message::Message; use solana_sdk::message::Message;
use anyhow::anyhow; use crate::dto::{AccountKeys, ParsedAccount, TokenData, TokenInfo, Transaction, TokenSocials };
use crate::utils::{base58_to_pubkey, get_token_socials};
use anyhow::Result; use anyhow::Result;
use anyhow::anyhow;
use base64::prelude::*; use base64::prelude::*;
use borsh::{BorshDeserialize, BorshSerialize}; use borsh::{BorshDeserialize, BorshSerialize};
use chrono::Utc; use chrono::Utc;
@ -17,6 +20,7 @@ use solana_client::rpc_client::RpcClient;
use solana_client::rpc_config::RpcAccountInfoConfig; use solana_client::rpc_config::RpcAccountInfoConfig;
use solana_client::rpc_request::TokenAccountsFilter; use solana_client::rpc_request::TokenAccountsFilter;
use solana_program::{program_pack::Pack, pubkey::Pubkey}; use solana_program::{program_pack::Pack, pubkey::Pubkey};
use solana_sdk::account::Account;
use solana_sdk::message::VersionedMessage; use solana_sdk::message::VersionedMessage;
use solana_sdk::signature::Signature; use solana_sdk::signature::Signature;
use solana_sdk::transaction::{TransactionError, VersionedTransaction}; use solana_sdk::transaction::{TransactionError, VersionedTransaction};
@ -25,21 +29,22 @@ use solana_transaction_status::{EncodedConfirmedTransactionWithStatusMeta, UiTra
use solana_transaction_status_client_types::option_serializer; use solana_transaction_status_client_types::option_serializer;
use spl_token::state::Mint; use spl_token::state::Mint;
use std::str::FromStr; use std::str::FromStr;
use solana_program::clock::Slot;
use solana_sdk::account::Account;
use utils::sanitize_string; use utils::sanitize_string;
use crate::dto::{AccountKeys, ParsedAccount, TokenData, TokenInfo, Transaction}; use solana_rpc_calls::*;
use crate::utils::base58_to_pubkey; use crate::telegram_publish::send_to_telegram;
mod utils;
mod dto; mod dto;
mod utils;
mod solana_rpc_calls;
mod telegram_publish;
lazy_static! { lazy_static! {
static ref RPC_CLIENT: RpcClient = static ref RPC_CLIENT: RpcClient =
RpcClient::new("https://api.mainnet-beta.solana.com".to_string()); RpcClient::new("https://api.mainnet-beta.solana.com".to_string());
} }
fn main() { #[tokio::main]
async fn main() {
// Adresse du programme Token (SPL Token Program) --> pumpfun // Adresse du programme Token (SPL Token Program) --> pumpfun
let token_program_address = "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM"; let token_program_address = "TSLvdd1pWpHVjahSpsvCXUbgwsL3JAcvokwaKt1eokM";
@ -58,12 +63,13 @@ fn main() {
match signatures { match signatures {
Ok(sigs) => { Ok(sigs) => {
debug!( debug!("{}", format!(
"{}", "Nombre total de transactions trouvées : {}",
format!("Nombre total de transactions trouvées : {}", sigs.len()) sigs.len()
); ));
for sig in sigs.iter().take(1000) { for sig in sigs.iter().take(1000) {
let signature = Signature::from_str(&sig.signature).unwrap(); let signature = Signature::from_str(&sig.signature).unwrap();
info!("================ Signature ========================"); info!("================ Signature ========================");
@ -87,105 +93,154 @@ fn main() {
}); });
if !is_token_creation { if !is_token_creation {
continue continue;
} }
match tx.transaction.transaction { match tx.transaction.transaction {
Binary(data, encoding) => { Binary(data, encoding) => {
let decoded = BASE64_STANDARD.decode(data).unwrap(); let decoded = BASE64_STANDARD.decode(data).unwrap();
if let Ok(versioned_tx) = if let Ok(versioned_tx) =
bincode::deserialize::<VersionedTransaction>( bincode::deserialize::<VersionedTransaction>(
&decoded, &decoded,
) )
{ {
let account_keys = versioned_tx.message.static_account_keys(); let account_keys =
versioned_tx.message.static_account_keys();
let transaction = Transaction { let transaction = Transaction {
signature: sig.clone().signature, signature: sig.clone().signature,
slot: sig.clone().slot, slot: sig.clone().slot,
block_time: sig.clone().block_time, block_time: sig.clone().block_time,
status: meta.err, status: meta.err,
account_keys: AccountKeys { account_keys: AccountKeys {
payer: account_keys[0], payer: account_keys[0],
mint_account: account_keys[1], mint_account: account_keys[1],
rent_account: account_keys[2], rent_account: account_keys[2],
mint_authority: account_keys[3], mint_authority: account_keys[3],
token_program: account_keys[4], token_program: account_keys[4],
}, },
}; };
let mint_pubkey =transaction.account_keys.mint_account; dbg!(&transaction);
let dev_pubkey = transaction.account_keys.payer; let mint_pubkey =
transaction.account_keys.mint_account;
match get_token_metadata( match get_token_metadata(
&RPC_CLIENT, &RPC_CLIENT,
&mint_pubkey, &mint_pubkey,
) { ) {
Ok(token_metadata) => { Ok(token_metadata) => {
let dev_balance =
let dev_balance = get_dev_balance_for_token(
get_dev_balance_for_token(
&RPC_CLIENT,
&transaction.account_keys.payer,
&mint_pubkey,
);
if let Err(e) = dev_balance {
error!("{}",format!("{}", e) );
continue
}
match get_token_info(
&RPC_CLIENT, &RPC_CLIENT,
&transaction.account_keys.payer,
&mint_pubkey, &mint_pubkey,
) { );
Ok(token_info) => {
let token_data = TokenData { if let Err(e) = dev_balance {
name: sanitize_string(&token_metadata.name), error!("{}", format!("{}", e));
symbol: sanitize_string(&token_metadata.symbol), continue;
uri: sanitize_string(&token_metadata.uri), }
supply: token_info.supply,
dev_balance: dev_balance.unwrap().clone(),
mint_authority: token_info.mint_authority,
freeze_authority: token_info.freeze_authority,
};
dbg!(token_data.clone()); match get_token_info(
&RPC_CLIENT,
&mint_pubkey,
) {
Ok(token_info) => {
let token_data = TokenData {
name: sanitize_string(
&token_metadata.name,
),
symbol: sanitize_string(
&token_metadata.symbol,
),
uri: sanitize_string(
&token_metadata.uri,
),
supply: token_info.supply / 10u64.pow(token_info.decimals as u32),
dev_balance: dev_balance
.unwrap()
.clone(),
mint_authority: token_info
.mint_authority,
freeze_authority:
token_info
.freeze_authority,
};
let is_safe_token = is_safe_token(token_data.clone()); dbg!(token_data.clone());
if(is_safe_token)
{
println!("Token OK")
}
else { println!("Token NOK") }
} let is_safe_token =
Err(e) => { is_safe_token(
error!( token_data.clone(),
"Erreur lors de la récupération des informations du token : {:?}",
e
); );
if (is_safe_token) {
println!("Token OK");
let token = "8176178685:AAHMlXsjx4ffH9sQ1v_eg1nkc-W9XUncIhE";
let chat_id = "945119667"; // can be a group chat too
let socials= get_token_socials(&token_data.uri).await.ok();
let socials = socials.unwrap_or_default();
let message = format!("🚨 #New token detected!\
\n**Name**: {} ({}) \
\n**Uri**: {} \
\nSignature: https://solscan.io/tx/{} \
\nMint address: https://solscan.io/token/{} \
\nDev address: https://solscan.io/account/{} \
\nSource: https://pump.fun/coin/{} \
\nDescription: {} \
\nTwitter: {} \
\nWebsite: {} \
\nImage: {} \
", token_data.name,
token_data.symbol,
token_data.uri,
transaction.signature,
transaction.account_keys.mint_account,
transaction.account_keys.payer,
transaction.account_keys.mint_account,
socials.description,
socials.twitter,
socials.website,
socials.image);
if let Err(e) = send_to_telegram(token, chat_id, message.as_str()).await {
eprintln!("Error sending to Telegram: {}", e);
}
} else {
println!("Token NOK")
} }
} }
Err(e) => {
error!(
"Erreur lors de la récupération des informations du token : {:?}",
e
);
}
} }
Err(_) => {} }
}; Err(_) => {}
} };
println!(
"============================================="
);
} }
_ => {}
println!(
"============================================="
);
} }
_ => {}
}
} }
} }
} }
@ -215,7 +270,6 @@ fn is_safe_token(data: TokenData) -> bool {
!(has_control || holds_too_much) !(has_control || holds_too_much)
} }
fn find_metadata_account(mint: &Pubkey) -> (Pubkey, u8) { fn find_metadata_account(mint: &Pubkey) -> (Pubkey, u8) {
let metadata_program_id = let metadata_program_id =
Pubkey::from_str("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s").unwrap(); Pubkey::from_str("metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s").unwrap();
@ -225,82 +279,6 @@ fn find_metadata_account(mint: &Pubkey) -> (Pubkey, u8) {
) )
} }
fn get_token_metadata(client: &RpcClient, mint: &Pubkey) -> Result<Metadata> {
let (metadata_pubkey, _) = find_metadata_account(mint);
let account = client.get_account(&metadata_pubkey)?;
let metadata = Metadata::safe_deserialize(&mut account.data.as_ref())?;
Ok(metadata)
}
pub const TOKEN_METADATA_PROGRAM_ID: Pubkey = Pubkey::new_from_array([
0x6D, 0x65, 0x74, 0x61, 0x70, 0x6C, 0x65, 0x78, 0x2D, 0x6D, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74,
0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
]);
fn get_creator_of_mint(rpc_client: &RpcClient, mint_address: &Pubkey) -> anyhow::Result<Pubkey> {
// 1. Récupère les signatures associées au compte mint
let signatures = rpc_client
.get_signatures_for_address(mint_address)
.into_iter()
.rev() // on inverse pour avoir les plus anciennes d'abord
.collect::<Vec<_>>();
let first_signature = signatures.first();
match first_signature {
None => Err(anyhow!("Pas de transactions trouvées pour ce mint")),
Some(sig) => {
let sig2 = sig.first().expect("Pzs de signature trouvée");
let sig = sig2
.signature
.parse::<Signature>()
.expect("Signature invalide");
// 2. Récupère les détails de la première transaction
let tx = get_transactions(rpc_client, &sig)?.transaction.transaction;
let tx: anyhow::Result<VersionedMessage> = match tx {
Binary(data, encoding) => {
let decoded = BASE64_STANDARD.decode(data)?;
if let Ok(versioned_tx) = bincode::deserialize::<VersionedTransaction>(&decoded)
{
if let Ok(message) = bincode::deserialize::<VersionedMessage>(
&versioned_tx.message.serialize(),
) {
Ok(message)
} else {
Err(anyhow!(""))
}
} else {
Err(anyhow!(""))
}
}
_ => Err(anyhow!("Encoding of transaction is not supported")),
};
let payer: Result<Message> = match tx {
Ok(msg) => {
match msg {
VersionedMessage::Legacy(legacy_msg) => {
println!("{:?}", legacy_msg);
Ok(legacy_msg)
}
//VersionedMessage::V0(v0_msg) => { println!("{:?}", v0_msg); v0_msg}
_ => Err(anyhow!("Encoding of transaction is not supported")),
}
}
Err(_) => Err(anyhow!("Encoding of transaction is not supported")),
};
let payer = payer;
Ok(*payer?.account_keys.first().unwrap())
}
}
}
fn is_token_creation(instruction: &solana_transaction_status::UiCompiledInstruction) -> bool { fn is_token_creation(instruction: &solana_transaction_status::UiCompiledInstruction) -> bool {
match bs58::decode(&instruction.data).into_vec() { match bs58::decode(&instruction.data).into_vec() {
@ -316,89 +294,6 @@ fn is_token_creation(instruction: &solana_transaction_status::UiCompiledInstruct
} }
} }
fn get_dev_balance_for_token(rpc: &RpcClient, dev_pubkey: &Pubkey, mint: &Pubkey) -> Result<f64> {
let token_accounts =
rpc.get_token_accounts_by_owner(dev_pubkey, TokenAccountsFilter::Mint(*mint))?;
let mut total_balance: f64 = 0.0;
for account_info in token_accounts {
let amount_option = match account_info.account.data.clone() {
UiAccountData::Json(test) => {
let json = serde_json::to_value(&test.parsed)?;
let token: ParsedAccount = serde_json::from_value(json)?;
token.info.tokenAmount.uiAmount
}
_ => {
error!("Cannot parse account_data");
None
}
};
total_balance += amount_option.unwrap_or_else(|| 0.0);
}
Ok(total_balance)
}
fn fetch_account(rpc_client: &RpcClient, mint_pubkey: &Pubkey) -> Result<Account> {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
..RpcAccountInfoConfig::default()
};
match rpc_client.get_account_with_config(&mint_pubkey, config) {
Ok(response) => {
match response.value {
Some(account) => {
Ok(account)
}
None => {
Err(anyhow::Error::msg(format!("Account not found")))
}
}
}
Err(e) => {
Err(anyhow::Error::msg(format!("RPC error {}", e)))
}
}
}
fn get_token_info(client: &RpcClient, mint_pubkey: &Pubkey) -> Result<TokenInfo> {
let account = fetch_account(client, mint_pubkey);
let mint = Mint::unpack(&*account?.data);
match mint {
Ok(mint) => {
Ok(TokenInfo {
mint_address: mint_pubkey.to_string(),
decimals: mint.decimals,
mint_authority: mint.mint_authority.is_some(),
freeze_authority: mint.freeze_authority.is_some(),
supply: mint.supply,
})
}
Err(e) => Err(anyhow::Error::msg(format!("ProgramError: {:?}", e))),
}
}
fn get_transactions(
client: &RpcClient,
signature: &Signature,
) -> solana_client::client_error::Result<EncodedConfirmedTransactionWithStatusMeta> {
let config = solana_client::rpc_config::RpcTransactionConfig {
encoding: Some(UiTransactionEncoding::Base64),
commitment: Some(solana_sdk::commitment_config::CommitmentConfig::confirmed()),
max_supported_transaction_version: Some(0),
};
client.get_transaction_with_config(&signature, config)
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;

98
src/solana_rpc_calls.rs Normal file
View File

@ -0,0 +1,98 @@
use anyhow::anyhow;
use base64::Engine;
use base64::prelude::BASE64_STANDARD;
use log::error;
use mpl_token_metadata::accounts::Metadata;
use solana_account_decoder::{UiAccountData, UiAccountEncoding};
use solana_client::rpc_client::RpcClient;
use solana_client::rpc_config::RpcAccountInfoConfig;
use solana_client::rpc_request::TokenAccountsFilter;
use solana_program::message::{Message, VersionedMessage};
use solana_program::program_pack::Pack;
use solana_program::pubkey::Pubkey;
use solana_sdk::account::Account;
use solana_sdk::signature::Signature;
use solana_sdk::transaction::VersionedTransaction;
use solana_transaction_status_client_types::{EncodedConfirmedTransactionWithStatusMeta, UiTransactionEncoding};
use solana_transaction_status_client_types::EncodedTransaction::Binary;
use spl_token::state::Mint;
use crate::dto::{ParsedAccount, TokenInfo};
use crate::{ find_metadata_account};
pub fn get_token_info(client: &RpcClient, mint_pubkey: &Pubkey) -> anyhow::Result<TokenInfo> {
let account = fetch_account(client, mint_pubkey);
let mint = Mint::unpack(&*account?.data);
match mint {
Ok(mint) => Ok(TokenInfo {
mint_address: mint_pubkey.to_string(),
decimals: mint.decimals,
mint_authority: mint.mint_authority.is_some(),
freeze_authority: mint.freeze_authority.is_some(),
supply: mint.supply,
}),
Err(e) => Err(anyhow::Error::msg(format!("ProgramError: {:?}", e))),
}
}
pub fn get_transactions(
client: &RpcClient,
signature: &Signature,
) -> solana_client::client_error::Result<EncodedConfirmedTransactionWithStatusMeta> {
let config = solana_client::rpc_config::RpcTransactionConfig {
encoding: Some(UiTransactionEncoding::Base64),
commitment: Some(solana_sdk::commitment_config::CommitmentConfig::confirmed()),
max_supported_transaction_version: Some(0),
};
client.get_transaction_with_config(&signature, config)
}
pub fn get_token_metadata(client: &RpcClient, mint: &Pubkey) -> anyhow::Result<Metadata> {
let (metadata_pubkey, _) = find_metadata_account(mint);
let account = client.get_account(&metadata_pubkey)?;
let metadata = Metadata::safe_deserialize(&mut account.data.as_ref())?;
Ok(metadata)
}
pub fn get_dev_balance_for_token(rpc: &RpcClient, dev_pubkey: &Pubkey, mint: &Pubkey) -> anyhow::Result<f64> {
let token_accounts =
rpc.get_token_accounts_by_owner(dev_pubkey, TokenAccountsFilter::Mint(*mint))?;
let mut total_balance: f64 = 0.0;
for account_info in token_accounts {
let amount_option = match account_info.account.data.clone() {
UiAccountData::Json(test) => {
let json = serde_json::to_value(&test.parsed)?;
let token: ParsedAccount = serde_json::from_value(json)?;
token.info.tokenAmount.uiAmount
}
_ => {
error!("Cannot parse account_data");
None
}
};
total_balance += amount_option.unwrap_or_else(|| 0.0);
}
Ok(total_balance)
}
fn fetch_account(rpc_client: &RpcClient, mint_pubkey: &Pubkey) -> anyhow::Result<Account> {
let config = RpcAccountInfoConfig {
encoding: Some(UiAccountEncoding::Base64),
..RpcAccountInfoConfig::default()
};
match rpc_client.get_account_with_config(&mint_pubkey, config) {
Ok(response) => match response.value {
Some(account) => Ok(account),
None => Err(anyhow::Error::msg(format!("Account not found"))),
},
Err(e) => Err(anyhow::Error::msg(format!("RPC error {}", e))),
}
}

20
src/telegram_publish.rs Normal file
View File

@ -0,0 +1,20 @@
use reqwest::Client;
pub async fn send_to_telegram(bot_token: &str, chat_id: &str, message: &str) -> Result<(), Box<dyn std::error::Error>> {
let url = format!("https://api.telegram.org/bot{}/sendMessage", bot_token);
let params = [
("chat_id", chat_id),
("text", message),
("parse_mode", "Markdown")
];
let client = Client::new();
client.post(&url)
.form(&params)
.send()
.await?;
Ok(())
}

View File

@ -1,4 +1,6 @@
use reqwest::Client;
use solana_program::pubkey::Pubkey; use solana_program::pubkey::Pubkey;
use crate::dto::TokenSocials;
pub fn sanitize_string(s: &str) -> String { pub fn sanitize_string(s: &str) -> String {
s.trim_end_matches('\0').to_string() s.trim_end_matches('\0').to_string()
@ -13,3 +15,14 @@ pub fn base58_to_pubkey(address: &str) -> anyhow::Result<Pubkey, Box<dyn std::er
bytes.copy_from_slice(&decoded); bytes.copy_from_slice(&decoded);
Ok(Pubkey::new_from_array(bytes)) Ok(Pubkey::new_from_array(bytes))
} }
pub async fn get_token_socials(uri: &str) -> Result<TokenSocials, Box<dyn std::error::Error>> {
let client = Client::new();
let response = client.get(uri)
.send()
.await?;
let json: TokenSocials = response.json().await?;
Ok(json)
}