diff --git a/dephy-vending_machine-examples/.github/dockerfiles/dephy-vending-machine-examples.dockerfile b/dephy-vending_machine-examples/.github/dockerfiles/dephy-vending-machine-examples.dockerfile new file mode 100644 index 0000000..6481442 --- /dev/null +++ b/dephy-vending_machine-examples/.github/dockerfiles/dephy-vending-machine-examples.dockerfile @@ -0,0 +1,14 @@ +FROM alpine:3.21 + +ARG TARGETPLATFORM + +ENV RUST_LOG=info + +WORKDIR /opt/dephy-vending-machine-examples +RUN adduser -D dephy --uid 1573 && chown -R dephy:dephy /opt/dephy-vending-machine-examples + +COPY ./${TARGETPLATFORM}/dephy-decharge-controller-server /usr/bin/dephy-decharge-controller-server +COPY ./${TARGETPLATFORM}/dephy-decharge-controller-node /usr/bin/dephy-decharge-controller-node +COPY ./${TARGETPLATFORM}/dephy-gacha-controller /usr/bin/dephy-gacha-controller + +USER dephy diff --git a/dephy-vending_machine-examples/.github/workflows/build_then_release.yml b/dephy-vending_machine-examples/.github/workflows/build_then_release.yml new file mode 100644 index 0000000..c3daf76 --- /dev/null +++ b/dephy-vending_machine-examples/.github/workflows/build_then_release.yml @@ -0,0 +1,170 @@ +name: Build then release + +on: + push: + tags: + - "v*" + branches: + - "main" + +env: + CARGO_TERM_COLOR: always + +jobs: + gen_version: + name: Generate version + runs-on: ubuntu-latest + outputs: + version: ${{ steps.generated-tag.outputs.tag }} + steps: + - uses: actions/checkout@v4 + - name: Get latest tag + id: get-latest-tag + run: | + echo "tag=`gh release list -L 1 | cut -f 1`" >> $GITHUB_OUTPUT + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Bump version + id: generated-tag + uses: actions/github-script@v6 + with: + script: | + if (context.ref.startsWith("refs/tags/")) { + let tag = context.ref.replace("refs/tags/", ""); + core.setOutput('tag', tag); + console.log(`This event pushed a tag ${tag}, return directly.`) + return + } + console.log('Use default tag "prerelease".') + core.setOutput('tag', 'prerelease'); + + build: + needs: gen_version + name: Build + runs-on: ${{ matrix.runner }} + strategy: + matrix: + include: + - target: x86_64-apple-darwin + runner: macos-latest + build_env: {} + - target: aarch64-apple-darwin + runner: macos-latest + build_env: {} + - target: x86_64-unknown-linux-musl + runner: ubuntu-latest + build_env: {} + - target: aarch64-unknown-linux-musl + runner: ubuntu-latest + build_env: + CARGO_TARGET_AARCH64_UNKNOWN_LINUX_MUSL_RUSTFLAGS: "-Clink-self-contained=yes -Clinker=rust-lld" + CC_aarch64_unknown_linux_musl: clang + AR_aarch64_unknown_linux_musl: llvm-ar + + steps: + - uses: actions/checkout@v4 + - name: Setup protoc + uses: arduino/setup-protoc@v3.0.0 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + - name: Install musl-tools + if: matrix.runner == 'ubuntu-latest' + run: sudo apt update && sudo apt install -y musl-tools + - name: Install cross build deps for aarch64-unknown-linux-musl + if: matrix.target == 'aarch64-unknown-linux-musl' + run: sudo apt update && sudo apt install -y clang llvm gcc-aarch64-linux-gnu + - name: Add target + run: rustup target add ${{ matrix.target }} + - name: Setup rust toolchain + run: rustup show + - uses: Swatinem/rust-cache@v2 + with: + shared-key: build-then-release-${{ matrix.target }}-v1 + - name: Build + env: ${{ matrix.build_env }} + run: | + cargo build --release --target ${{ matrix.target }} + - name: Compress + run: | + zip -j dephy-decharge-controller-node-${{ needs.gen_version.outputs.version }}-${{ matrix.target }}.zip ./target/${{ matrix.target }}/release/dephy-decharge-controller-node && + zip -j dephy-decharge-controller-server-${{ needs.gen_version.outputs.version }}-${{ matrix.target }}.zip ./target/${{ matrix.target }}/release/dephy-decharge-controller-server && + zip -j dephy-gacha-controller-${{ needs.gen_version.outputs.version }}-${{ matrix.target }}.zip ./target/${{ matrix.target }}/release/dephy-gacha-controller + - uses: actions/upload-artifact@v4 + name: Upload artifacts + with: + name: dephy-vending-machine-examples-${{ needs.gen_version.outputs.version }}-${{ matrix.target }} + path: "*.zip" + retention-days: 1 + + release: + needs: [gen_version, build] + runs-on: ubuntu-latest + permissions: + contents: write + steps: + - uses: actions/checkout@v4 + - name: Generate changelog + uses: orhun/git-cliff-action@v3 + id: git-cliff + with: + config: cliff.toml + args: "-vv --strip header ${{ needs.gen_version.outputs.version == 'prerelease' && '--unreleased' || '--latest' }}" + - uses: actions/download-artifact@v4 + - name: Display fetched artifacts + run: ls -R + - uses: softprops/action-gh-release@v2.0.6 + name: Emit a Github Release + with: + token: "${{ secrets.GITHUB_TOKEN }}" + body: "${{ steps.git-cliff.outputs.content }}" + tag_name: ${{ needs.gen_version.outputs.version }} + prerelease: ${{ needs.gen_version.outputs.version == 'prerelease' }} + files: | + LICENSE + dephy-vending-machine-examples-${{ needs.gen_version.outputs.version }}-x86_64-apple-darwin/*.zip + dephy-vending-machine-examples-${{ needs.gen_version.outputs.version }}-aarch64-apple-darwin/*.zip + dephy-vending-machine-examples-${{ needs.gen_version.outputs.version }}-x86_64-unknown-linux-musl/*.zip + dephy-vending-machine-examples-${{ needs.gen_version.outputs.version }}-aarch64-unknown-linux-musl/*.zip + + image: + needs: [gen_version, build] + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - uses: actions/download-artifact@v4 + - name: Log in to the Container registry + uses: docker/login-action@v3.3.0 + with: + username: ${{ vars.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@v5.6.1 + with: + images: ${{ vars.DOCKERHUB_USERNAME }}/dephy-vending-machine-examples + - name: Extract all released executable files + run: | + for dir in dephy-vending-machine-examples-${{ needs.gen_version.outputs.version }}-*/; do + for zip_file in "$dir"*.zip; do + [ -f "$zip_file" ] && unzip "$zip_file" -d "$dir" && rm "$zip_file" + done + done + - name: Display fetched artifacts + run: ls -R + - name: Move directory for platforms + run: | + mkdir linux && + mv dephy-vending-machine-examples-${{ needs.gen_version.outputs.version }}-x86_64-unknown-linux-musl linux/amd64 && + mv dephy-vending-machine-examples-${{ needs.gen_version.outputs.version }}-aarch64-unknown-linux-musl linux/arm64 + - name: Display moved files + run: ls -R + - name: Build and push Docker image + id: push + uses: docker/build-push-action@v6.10.0 + with: + file: ./.github/dockerfiles/dephy-vending-machine-examples.dockerfile + context: . + platforms: linux/amd64,linux/arm64 + tags: ${{ steps.meta.outputs.tags }} + push: true diff --git a/dephy-vending_machine-examples/.github/workflows/check_and_test.yml b/dephy-vending_machine-examples/.github/workflows/check_and_test.yml new file mode 100644 index 0000000..a9755e1 --- /dev/null +++ b/dephy-vending_machine-examples/.github/workflows/check_and_test.yml @@ -0,0 +1,40 @@ +name: Check and test + +on: + push: + branches: + - main + pull_request: + branches: + - main + +env: + CARGO_TERM_COLOR: always + +jobs: + test: + name: Check and test + strategy: + matrix: + platform: [ubuntu-latest] + runs-on: ${{ matrix.platform }} + steps: + - uses: actions/checkout@v4 + - name: Setup rust toolchain + run: | + rustup install nightly + rustup component add rustfmt --toolchain nightly + rustup show + - name: Install nextest + uses: taiki-e/install-action@nextest + - uses: Swatinem/rust-cache@v2 + with: + shared-key: check-and-test-${{ matrix.platform }}-v1 + - name: Check code format + run: cargo +nightly fmt -- --check + - name: Check the package for errors + run: cargo check --all + - name: Lint rust sources + run: cargo clippy --all-targets --all-features --tests --benches -- -D warnings + - name: Execute rust tests + run: cargo nextest run --all-features --no-tests=pass diff --git a/dephy-vending_machine-examples/.gitignore b/dephy-vending_machine-examples/.gitignore new file mode 100644 index 0000000..f60c29a --- /dev/null +++ b/dephy-vending_machine-examples/.gitignore @@ -0,0 +1,13 @@ +.env +.DS_Store +target +.anchor +*.rs.bk +node_modules +test-ledger +.yarn +bun.lock +bun.lockb +package-lock.json +data +tmp diff --git a/dephy-vending_machine-examples/.pre-commit-config.yaml b/dephy-vending_machine-examples/.pre-commit-config.yaml new file mode 100644 index 0000000..688e9d0 --- /dev/null +++ b/dephy-vending_machine-examples/.pre-commit-config.yaml @@ -0,0 +1,54 @@ +fail_fast: false +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.6.0 + hooks: + - id: check-case-conflict + - id: check-merge-conflict + - id: check-symlinks + - id: check-yaml + - id: end-of-file-fixer + - id: fix-byte-order-marker + - id: mixed-line-ending + - id: trailing-whitespace + - repo: local + hooks: + - id: taplo + name: taplo format + description: Format Cargo.toml files with taplo. + entry: bash -c 'taplo format --check' + language: rust + files: Cargo.toml$ + - id: cargo-fmt + name: cargo fmt + description: Format files with rustfmt. + entry: bash -c 'cargo +nightly fmt -- --check' + language: rust + files: \.rs$ + - id: cargo-deny + name: cargo deny check + description: Check cargo dependencies + entry: bash -c 'cargo deny check -d' + language: rust + files: \.*$ + - id: typos + name: typos + description: check typo + entry: bash -c 'typos' + language: rust + files: \.*$ + pass_filenames: false + - id: cargo-check + name: cargo check + description: Check the package for errors. + entry: bash -c 'cargo check --all' + language: rust + files: \.rs$ + pass_filenames: false + - id: cargo-clippy + name: cargo clippy + description: Lint rust sources + entry: bash -c 'cargo clippy --all-targets --all-features --tests --benches -- -D warnings' + language: rust + files: \.rs$ + pass_filenames: false diff --git a/dephy-vending_machine-examples/.prettierignore b/dephy-vending_machine-examples/.prettierignore new file mode 100644 index 0000000..1c26229 --- /dev/null +++ b/dephy-vending_machine-examples/.prettierignore @@ -0,0 +1,9 @@ +.anchor +.DS_Store +target +node_modules +dist +build +test-ledger + +bun.lockb diff --git a/dephy-vending_machine-examples/Cargo.lock b/dephy-vending_machine-examples/Cargo.lock new file mode 100644 index 0000000..71bcf68 --- /dev/null +++ b/dephy-vending_machine-examples/Cargo.lock @@ -0,0 +1,7413 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle", + "zeroize", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom 0.2.15", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" +dependencies = [ + "anstyle", + "once_cell", + "windows-sys 0.59.0", +] + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint 0.4.6", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint 0.4.6", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-compression" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.4.0", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-trait" +version = "0.1.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "async-utility" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34a3b57207a7a1007832416c3e4862378c8451b4e8e093e436f48c2d3d2c151" +dependencies = [ + "futures-util", + "gloo-timers", + "tokio", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-wsocket" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34d2efbc332d581321b37a3012c942b0555483030b5cfc1325a95c386b11e27b" +dependencies = [ + "async-utility", + "futures", + "futures-util", + "js-sys", + "tokio", + "tokio-rustls 0.26.1", + "tokio-socks", + "tokio-tungstenite 0.24.0", + "url", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + +[[package]] +name = "atomic-destructor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef49f5882e4b6afaac09ad239a4f8c70a24b8f2b0897edb1f706008efd109cf4" + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals 0.3.0", + "bitcoin_hashes 0.14.0", +] + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "bech32" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d965446196e3b7decd44aa7ee49e31d630118f90ef12f97900f262eb915c951d" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bip39" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33415e24172c1b7d6066f6d999545375ab8e1d95421d6784bdfff9496f292387" +dependencies = [ + "bitcoin_hashes 0.13.0", + "serde", + "unicode-normalization", +] + +[[package]] +name = "bitcoin" +version = "0.32.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce6bc65742dea50536e35ad42492b234c27904a27f0abdcbce605015cb4ea026" +dependencies = [ + "base58ck", + "bech32", + "bitcoin-internals 0.3.0", + "bitcoin-io", + "bitcoin-units", + "bitcoin_hashes 0.14.0", + "hex-conservative 0.2.1", + "hex_lit", + "secp256k1", + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9425c3bf7089c983facbae04de54513cce73b41c7f9ff8c845b54e7bc64ebbfb" + +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +dependencies = [ + "serde", +] + +[[package]] +name = "bitcoin-io" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" + +[[package]] +name = "bitcoin-units" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +dependencies = [ + "bitcoin-internals 0.3.0", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1930a4dabfebb8d7d9992db18ebe3ae2876f0a305fab206fd168df931ede293b" +dependencies = [ + "bitcoin-internals 0.2.0", + "hex-conservative 0.1.2", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +dependencies = [ + "bitcoin-io", + "hex-conservative 0.2.1", + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +dependencies = [ + "serde", +] + +[[package]] +name = "blake3" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "borsh" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" +dependencies = [ + "borsh-derive 0.10.4", + "hashbrown 0.13.2", +] + +[[package]] +name = "borsh" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc" +dependencies = [ + "borsh-derive 1.5.5", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8b668d39970baad5356d7c83a86fee3a539e6f93bf6764c97368243e17a0487" +dependencies = [ + "once_cell", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "brotli" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" + +[[package]] +name = "caps" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" +dependencies = [ + "libc", + "thiserror 1.0.69", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + +[[package]] +name = "cc" +version = "1.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7777341816418c02e033934a09f20dc0ccaf65a5201ef8a450ae0105a573fda" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cfg_eval" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chacha20poly1305" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" +dependencies = [ + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", +] + +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets 0.52.6", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "clap" +version = "4.5.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acebd8ad879283633b343856142139f2da2317c96b05b4dd6181c61e2480184" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.5.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ba32cbda51c7e1dfd49acc1457ba1a7dec5b64fe360e828acb13ca8dc9c2f9" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + +[[package]] +name = "colorchoice" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rand_core 0.6.4", + "rustc_version", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.98", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010" + +[[package]] +name = "dephy-balance-payment-sdk" +version = "0.1.0" +dependencies = [ + "arrayref", + "borsh 0.10.4", + "curve25519-dalek 4.1.3", + "num-derive", + "num-traits", + "serde", + "serde_json", + "serde_with", + "sha2 0.10.8", + "solana-client", + "solana-program", + "solana-sdk", + "solana-zk-token-sdk", + "thiserror 2.0.11", + "tracing", +] + +[[package]] +name = "dephy-decharge-controller" +version = "0.1.0" +dependencies = [ + "clap", + "dephy-balance-payment-sdk", + "futures", + "nostr", + "nostr-sdk", + "sea-query", + "sea-query-binder", + "serde", + "serde_json", + "sqlx", + "thiserror 2.0.11", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "dephy-gacha-controller" +version = "0.1.0" +dependencies = [ + "clap", + "dephy-balance-payment-sdk", + "futures", + "nostr", + "nostr-sdk", + "serde", + "serde_json", + "thiserror 2.0.11", + "tokio", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint 0.4.6", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivation-path" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "dlopen2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cbae11b3de8fce2a456e8ea3dada226b35fe791f0dc1d360c0941f0bb681f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature 1.6.4", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.0", + "ed25519", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-dalek-bip32" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" +dependencies = [ + "derivation-path", + "ed25519-dalek", + "hmac 0.12.1", + "sha2 0.10.8", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +dependencies = [ + "serde", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +dependencies = [ + "event-listener 5.4.0", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "feature-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "five8_const" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b4f62f0f8ca357f93ae90c8c2dd1041a1f665fde2f889ea9b1787903829015" +dependencies = [ + "five8_core", +] + +[[package]] +name = "five8_core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94474d15a76982be62ca8a39570dccce148d98c238ebb7408b0a21b2c4bdddc4" + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "governor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" +dependencies = [ + "cfg-if", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand 0.8.5", + "smallvec", + "spinning_top", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap 2.7.1", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + +[[package]] +name = "hashlink" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +dependencies = [ + "hashbrown 0.15.2", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212ab92002354b4819390025006c897e8140934349e8635c9b077f47b4dcbd20" + +[[package]] +name = "hex-conservative" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "histogram" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac 0.12.1", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "home" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", + "serde", +] + +[[package]] +name = "indicatif" +version = "0.17.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + +[[package]] +name = "inherent" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0122b7114117e64a63ac49f752a5ca4624d534c7b1c7de796ac196381cd2d947" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +dependencies = [ + "futures", + "futures-executor", + "futures-util", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libm" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" + +[[package]] +name = "libsecp256k1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsqlite3-sys" +version = "0.30.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" +dependencies = [ + "pkg-config", + "vcpkg", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest 0.10.7", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "negentropy" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e664971378a3987224f7a0e10059782035e89899ae403718ee07de85bec42afe" + +[[package]] +name = "negentropy" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a88da9dd148bbcdce323dd6ac47d369b4769d4a3b78c6c52389b9269f77932" + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.8.0", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + +[[package]] +name = "nostr" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7c1eebe17dd785e52e1f81149c1b50fa6ec92e4ac239840934d1ffbd4f631c" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bech32", + "bip39", + "bitcoin", + "cbc", + "chacha20", + "chacha20poly1305", + "getrandom 0.2.15", + "instant", + "negentropy 0.3.1", + "negentropy 0.4.3", + "once_cell", + "scrypt", + "serde", + "serde_json", + "unicode-normalization", + "url", +] + +[[package]] +name = "nostr-database" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c175f769291b39e399905c1e1f0dcde0ea4959642db50a9a97f47fe73fac947" +dependencies = [ + "async-trait", + "nostr", + "tokio", +] + +[[package]] +name = "nostr-relay-pool" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0a11b3d117d729b32efffacf7566ec6845e96e836cfab32c61b818cf90f8e4" +dependencies = [ + "async-utility", + "async-wsocket", + "atomic-destructor", + "negentropy 0.3.1", + "negentropy 0.4.3", + "nostr", + "nostr-database", + "tokio", + "tracing", +] + +[[package]] +name = "nostr-sdk" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dce4741c6b4bcb46fe5fdf6834c64b2d8aee090264319aa4749f268e20ace111" +dependencies = [ + "async-utility", + "nostr", + "nostr-database", + "nostr-relay-pool", + "tokio", + "tracing", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +dependencies = [ + "num-bigint 0.2.6", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-bigint 0.2.6", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi 0.3.9", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945462a4b81e43c4e3ba96bd7b49d834c6f61198356aa858733bc4acf3cbe62e" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl" +version = "0.10.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61cfb4e166a8bb8c9b55c500bc2308550148ece889be90f609377e58140f42c6" +dependencies = [ + "bitflags 2.8.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-src" +version = "300.4.1+3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.105" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b22d5b84be05a8d6947c7cb71f7c849aa0f112acd4bf51c2a7c1c988ac0a9dc" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest 0.10.7", + "hmac 0.12.1", +] + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "percentage" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd23b938276f14057220b707937bcb42fa76dda7560e57a2da30cb52d557937" +dependencies = [ + "num", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "qstring" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "quanta" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bd1fe6824cea6538803de3ff1bc0cf3949024db3d43c9643024bfb33a807c0e" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi 0.11.0+wasi-snapshot-preview1", + "web-sys", + "winapi", +] + +[[package]] +name = "quinn" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.23", + "socket2", + "thiserror 2.0.11", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +dependencies = [ + "bytes", + "getrandom 0.2.15", + "rand 0.8.5", + "ring", + "rustc-hash", + "rustls 0.23.23", + "rustls-pki-types", + "rustls-platform-verifier", + "slab", + "thiserror 2.0.11", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-cpuid" +version = "11.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6928fa44c097620b706542d428957635951bade7143269085389d42c8a4927e" +dependencies = [ + "bitflags 2.8.0", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.8.0", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "async-compression", + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http 0.2.12", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.25.4", + "winreg", +] + +[[package]] +name = "reqwest-middleware" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216" +dependencies = [ + "anyhow", + "async-trait", + "http 0.2.12", + "reqwest", + "serde", + "task-local-extensions", + "thiserror 1.0.69", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.15", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rsa" +version = "0.9.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" +dependencies = [ + "const-oid", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature 2.2.0", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.8.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.23.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.2.0", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "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]] +name = "rustls-pki-types" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" +dependencies = [ + "web-time", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c7dc240fec5517e6c4eab3310438636cfe6391dfc345ba013109909a90d136" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.23", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki 0.102.8", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] +name = "ryu" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" + +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2 0.12.2", + "salsa20", + "sha2 0.10.8", +] + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "sea-query" +version = "0.32.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "085e94f7d7271c0393ac2d164a39994b1dff1b06bc40cd9a0da04f3d672b0fee" +dependencies = [ + "inherent", + "sea-query-derive", +] + +[[package]] +name = "sea-query-binder" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0019f47430f7995af63deda77e238c17323359af241233ec768aba1faea7608" +dependencies = [ + "sea-query", + "sqlx", +] + +[[package]] +name = "sea-query-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9834af2c4bd8c5162f00c89f1701fb6886119a88062cf76fe842ea9e232b9839" +dependencies = [ + "darling", + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.98", + "thiserror 1.0.69", +] + +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "bitcoin_hashes 0.14.0", + "rand 0.8.5", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.8.0", + "core-foundation", + "core-foundation-sys", + "libc", + "num-bigint 0.4.6", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-big-array" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11fc7cc2c76d73e0f27ee52abbd64eec84d46f370c88371120433196934e4b7f" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "serde_json" +version = "1.0.138" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949" +dependencies = [ + "indexmap 2.7.1", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.7.1", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "solana-account" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8921f616711771b71d4828f741c41d0cc6ab20937f62434b92335acf0c328f11" +dependencies = [ + "bincode", + "serde", + "serde_bytes", + "serde_derive", + "solana-account-info", + "solana-clock", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-sysvar", +] + +[[package]] +name = "solana-account-decoder-client-types" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "base64 0.22.1", + "bs58", + "serde", + "serde_derive", + "serde_json", + "solana-account", + "solana-pubkey", + "zstd", +] + +[[package]] +name = "solana-account-info" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d3d8a883f0e6928427a2dcceeb33ec7d87c47ec349a78d446a8357acc415cf" +dependencies = [ + "bincode", + "serde", + "solana-program-error", + "solana-program-memory", + "solana-pubkey", +] + +[[package]] +name = "solana-address-lookup-table-interface" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f002d5b24d29a0a9ceb7fad82a7fcad5f68b2b1c04b4dd1fe514a4ee634a50" +dependencies = [ + "bincode", + "bytemuck", + "serde", + "serde_derive", + "solana-clock", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-slot-hashes", +] + +[[package]] +name = "solana-atomic-u64" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180aa1d8a66a709cf6e1ed030607e20c1db8b542ee864c6d4cf33d43fea338e5" +dependencies = [ + "parking_lot", +] + +[[package]] +name = "solana-big-mod-exp" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b28c7604fe6e94ce5d05c8f9d171a57adc707f908731bda74c18645391c398a" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "solana-define-syscall", +] + +[[package]] +name = "solana-bincode" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5077f558a6fa420a30e1552824fa3c7e80f69429c5bfa60480362f1de4ef985" +dependencies = [ + "bincode", + "serde", + "solana-instruction", +] + +[[package]] +name = "solana-blake3-hasher" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb9a054858932c63a4c96cbe1a8fae8770e79dfe2d0bf07e0b26d03ebc6403ca" +dependencies = [ + "blake3", + "solana-define-syscall", + "solana-hash", + "solana-sanitize", +] + +[[package]] +name = "solana-bn254" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d25219261a38b268f97aea960f35ee7e9dc087c269d0952aa5c3e3aad8b735f" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "bytemuck", + "solana-define-syscall", + "thiserror 2.0.11", +] + +[[package]] +name = "solana-borsh" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bd8ebd23d44ddfb3b6cb887499ceae1fea0c1dc63fc1a441a8b82192185f4b7" +dependencies = [ + "borsh 0.10.4", + "borsh 1.5.5", +] + +[[package]] +name = "solana-client" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "async-trait", + "bincode", + "dashmap", + "futures", + "futures-util", + "indexmap 2.7.1", + "indicatif", + "log", + "quinn", + "rayon", + "solana-account", + "solana-client-traits", + "solana-commitment-config", + "solana-connection-cache", + "solana-epoch-info", + "solana-hash", + "solana-instruction", + "solana-keypair", + "solana-measure", + "solana-message", + "solana-pubkey", + "solana-pubsub-client", + "solana-quic-client", + "solana-quic-definitions", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-rpc-client-nonce-utils", + "solana-signature", + "solana-signer", + "solana-streamer", + "solana-thin-client", + "solana-time-utils", + "solana-tpu-client", + "solana-transaction", + "solana-transaction-error", + "solana-udp-client", + "thiserror 2.0.11", + "tokio", +] + +[[package]] +name = "solana-client-traits" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ae616269c74fe3e8f0193a631513057074d54d753605685afca7f0421cfb844" +dependencies = [ + "solana-account", + "solana-commitment-config", + "solana-epoch-info", + "solana-hash", + "solana-instruction", + "solana-keypair", + "solana-message", + "solana-pubkey", + "solana-signature", + "solana-signer", + "solana-system-interface", + "solana-transaction", + "solana-transaction-error", +] + +[[package]] +name = "solana-clock" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ee21be92dbcfc3240536fa9615bf5418db2e373d3ba794baf3c63d8d17d85aa" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-cluster-type" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be3d6c005c60c9895c9beeaa4d157ffeba4dcd2eea6cada3ba4edcc0a3ece39f" +dependencies = [ + "serde", + "serde_derive", + "solana-hash", +] + +[[package]] +name = "solana-commitment-config" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fef9ace627762305f68784868f1ecaea2bccb5dc658850d6a9f1818fbcecadc" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "solana-compute-budget-interface" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf6f360539a44a5e2f27aded0696b64799e57dd6678423fb5f40b4433940cea" +dependencies = [ + "borsh 1.5.5", + "serde", + "serde_derive", + "solana-instruction", + "solana-sdk-ids", +] + +[[package]] +name = "solana-connection-cache" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "async-trait", + "bincode", + "crossbeam-channel", + "futures-util", + "indexmap 2.7.1", + "log", + "rand 0.8.5", + "rayon", + "solana-keypair", + "solana-measure", + "solana-metrics", + "solana-net-utils", + "solana-time-utils", + "solana-transaction-error", + "thiserror 2.0.11", + "tokio", +] + +[[package]] +name = "solana-cpi" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be0ef159507ece00b3ae2e6c68055fb1ebe161d1c22ba0f33041ba3eb1a21eb3" +dependencies = [ + "solana-account-info", + "solana-define-syscall", + "solana-instruction", + "solana-program-error", + "solana-pubkey", + "solana-stable-layout", +] + +[[package]] +name = "solana-curve25519" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "solana-define-syscall", + "subtle", + "thiserror 2.0.11", +] + +[[package]] +name = "solana-decode-error" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2249dcb5383b8f91777475eaffb71192be5ffa2b2f7ef34b89b4fa2975f0bed" +dependencies = [ + "num-traits", +] + +[[package]] +name = "solana-define-syscall" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "acfe725269aac42d044cca5a99cfe8bd3b3f10e8d429b51f0c274e434fb34556" + +[[package]] +name = "solana-derivation-path" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6f0b5beefd88b57fabb7d83fa4239e3dcddb779244f81488a800f5e09ba187c" +dependencies = [ + "derivation-path", + "qstring", + "uriparse", +] + +[[package]] +name = "solana-ed25519-program" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1a61c5e5f1dae28957daabf1809c918700d0ad9ddc5c43b4b85e30ad445b7d" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "ed25519-dalek", + "solana-feature-set", + "solana-instruction", + "solana-precompile-error", + "solana-sdk-ids", +] + +[[package]] +name = "solana-epoch-info" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff88883795bc1cde6e089d10ce87d9abe78614317408c67b9e98b7e6e7fe680" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "solana-epoch-rewards" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6519f3178a03bbb7d36c0068f4276293de8b81aa87d15f11b2f9968778bbe84d" +dependencies = [ + "serde", + "serde_derive", + "solana-hash", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-epoch-rewards-hasher" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1781e2555534e7cf57fd7832b06118f42ea6519d31b03afc90ff1932fe831681" +dependencies = [ + "siphasher", + "solana-hash", + "solana-pubkey", +] + +[[package]] +name = "solana-epoch-schedule" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c616297c19a097a8f718c0abff0f23c0f80baccaddc24306a1b4701b0e5af60" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-example-mocks" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f024993f59c085cde2c265a87035b139221c168266c51e1ef2c0c817d14172f" +dependencies = [ + "serde", + "serde_derive", + "solana-address-lookup-table-interface", + "solana-clock", + "solana-hash", + "solana-instruction", + "solana-keccak-hasher", + "solana-message", + "solana-nonce", + "solana-pubkey", + "solana-sdk-ids", + "solana-system-interface", + "thiserror 2.0.11", +] + +[[package]] +name = "solana-feature-gate-interface" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c1880be2f4b4f94c58338e081cea0fd8e5381c73b60272ca6746af277c74bb1" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account", + "solana-account-info", + "solana-instruction", + "solana-program-error", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-system-interface", +] + +[[package]] +name = "solana-feature-set" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64433def9f89551638460ab3443a2b72fb91f4f0cf9b79e7f56345068f60e2d" +dependencies = [ + "ahash", + "lazy_static", + "solana-epoch-schedule", + "solana-hash", + "solana-pubkey", + "solana-sha256-hasher", +] + +[[package]] +name = "solana-fee-calculator" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6efed4a994807173cc48c66c5983c5b965dc4e27ee8b85c21290eb6178cc342" +dependencies = [ + "log", + "serde", + "serde_derive", +] + +[[package]] +name = "solana-fee-structure" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051c6d8c8b35b4c302e4de0a9c2dff9178a400611179002210edcb053fb4c86d" +dependencies = [ + "serde", + "serde_derive", + "solana-message", + "solana-native-token", +] + +[[package]] +name = "solana-genesis-config" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26551a9c57b499b7aef4fae92748ba2329a168b3e9b8fce6a3f22dbb2ef4e05c" +dependencies = [ + "bincode", + "chrono", + "memmap2", + "serde", + "serde_derive", + "solana-account", + "solana-clock", + "solana-cluster-type", + "solana-epoch-schedule", + "solana-fee-calculator", + "solana-hash", + "solana-inflation", + "solana-keypair", + "solana-logger", + "solana-native-token", + "solana-poh-config", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-sha256-hasher", + "solana-shred-version", + "solana-signer", + "solana-time-utils", +] + +[[package]] +name = "solana-hard-forks" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad74d3fe543f080551d479da3bcd0b982508ec2d5c38a0c79c76684cfef0aa0" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "solana-hash" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7e29a5aba505e381c8251d2b7c4f87676ede47f874f676b82c897309c79fca" +dependencies = [ + "borsh 1.5.5", + "bs58", + "bytemuck", + "bytemuck_derive", + "js-sys", + "serde", + "serde_derive", + "solana-atomic-u64", + "solana-sanitize", + "wasm-bindgen", +] + +[[package]] +name = "solana-inflation" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71a542351ed9d79de87dadaff20cb2e9bb28d608418b4f6355f0bd8d5e09d94" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "solana-inline-spl" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "bytemuck", + "solana-pubkey", +] + +[[package]] +name = "solana-instruction" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "203a473c569413392fcbae76e7c0cc316384f2231d22314a0e45f8bf49fdf33b" +dependencies = [ + "bincode", + "borsh 1.5.5", + "getrandom 0.2.15", + "js-sys", + "num-traits", + "serde", + "serde_derive", + "solana-define-syscall", + "solana-pubkey", + "wasm-bindgen", +] + +[[package]] +name = "solana-instructions-sysvar" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6da5b2a406cb19ac7833cfe784d8084a146816ea30388bda39fd53ab2db8857a" +dependencies = [ + "bitflags 2.8.0", + "solana-account-info", + "solana-instruction", + "solana-program-error", + "solana-pubkey", + "solana-sanitize", + "solana-sdk-ids", + "solana-serialize-utils", + "solana-sysvar-id", +] + +[[package]] +name = "solana-keccak-hasher" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5f21b6ebb03ac2dcfb39a89f6d3c1f5c90498acb7679c613cb1eaad6e2f70c9" +dependencies = [ + "sha3", + "solana-define-syscall", + "solana-hash", + "solana-sanitize", +] + +[[package]] +name = "solana-keypair" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4204e3120e9a568bb148759367f2adeca0e1ad32de52aab641b113fd2f8735c3" +dependencies = [ + "bs58", + "ed25519-dalek", + "ed25519-dalek-bip32", + "rand 0.7.3", + "solana-derivation-path", + "solana-pubkey", + "solana-seed-derivable", + "solana-seed-phrase", + "solana-signature", + "solana-signer", + "wasm-bindgen", +] + +[[package]] +name = "solana-last-restart-slot" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ba8f2feb1a64f46a65ad0c86582c0a62d664480be04ca51f1f0aed525a86b9" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-loader-v2-interface" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ae2d3ab2587687b807747e06be802c34cd4187013b3de9053431db30cc7fb8" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", +] + +[[package]] +name = "solana-loader-v3-interface" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feef12d4276f615604a36a3ae2088164fd5fffee487e1e62318751c7550a4f63" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-system-interface", +] + +[[package]] +name = "solana-loader-v4-interface" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7106bc1ec1edf234c99c85e4a8cd8978ccb91ebfd69f9b86e5fad8378c4f9a17" +dependencies = [ + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-system-interface", +] + +[[package]] +name = "solana-logger" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84cfc2f547fee3ee1bd91b0d3afcb04d9d8a6ed5a14d64274cfdc68c340020f6" +dependencies = [ + "env_logger", + "lazy_static", + "log", +] + +[[package]] +name = "solana-measure" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" + +[[package]] +name = "solana-message" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0956ed485c297d9a472652e607b34f010dec33f91c7d20e80aa91bf92e8ec169" +dependencies = [ + "bincode", + "blake3", + "lazy_static", + "serde", + "serde_derive", + "solana-bincode", + "solana-hash", + "solana-instruction", + "solana-pubkey", + "solana-sanitize", + "solana-sdk-ids", + "solana-short-vec", + "solana-system-interface", + "solana-transaction-error", + "wasm-bindgen", +] + +[[package]] +name = "solana-metrics" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "crossbeam-channel", + "gethostname", + "lazy_static", + "log", + "reqwest", + "solana-clock", + "solana-cluster-type", + "solana-sha256-hasher", + "solana-time-utils", + "thiserror 2.0.11", +] + +[[package]] +name = "solana-msg" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b17b5e3bebc5d8c8e64c2db7e42aac0232290833c8c28cb3c45ee383f1a237d" +dependencies = [ + "solana-define-syscall", +] + +[[package]] +name = "solana-native-token" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f51c5e81d3dda6bb68668c23bb8d591518fbbcdaccc8673dcc44a773f049622a" + +[[package]] +name = "solana-net-utils" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "anyhow", + "bincode", + "bytes", + "crossbeam-channel", + "itertools 0.12.1", + "log", + "nix", + "rand 0.8.5", + "serde", + "serde_derive", + "socket2", + "solana-serde", + "tokio", + "url", +] + +[[package]] +name = "solana-nonce" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d9d856214dfd16804d11008537ae10320577b65828b8eae5bd9b1f065d3f8b" +dependencies = [ + "serde", + "serde_derive", + "solana-fee-calculator", + "solana-hash", + "solana-pubkey", + "solana-sha256-hasher", +] + +[[package]] +name = "solana-nonce-account" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d9836c27351b21c46b187b6196f531815ba1dcab007b60fd576784b611517a" +dependencies = [ + "solana-account", + "solana-hash", + "solana-nonce", + "solana-sdk-ids", +] + +[[package]] +name = "solana-offchain-message" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d9306d45394521335d6b8f8b8d6b333526da2f44d7e9c39b32ffe61f763015c" +dependencies = [ + "num_enum", + "solana-hash", + "solana-packet", + "solana-pubkey", + "solana-sanitize", + "solana-sha256-hasher", + "solana-signature", + "solana-signer", +] + +[[package]] +name = "solana-packet" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49f415630073dd29449f5555a88165e5dc3fc91fe105252bcab08c3ae30f732" +dependencies = [ + "bincode", + "bitflags 2.8.0", + "cfg_eval", + "serde", + "serde_derive", + "serde_with", +] + +[[package]] +name = "solana-perf" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "ahash", + "bincode", + "bv", + "caps", + "curve25519-dalek 4.1.3", + "dlopen2", + "fnv", + "lazy_static", + "libc", + "log", + "nix", + "rand 0.8.5", + "rayon", + "serde", + "solana-hash", + "solana-message", + "solana-metrics", + "solana-packet", + "solana-pubkey", + "solana-rayon-threadlimit", + "solana-sdk-ids", + "solana-short-vec", + "solana-signature", + "solana-time-utils", +] + +[[package]] +name = "solana-poh-config" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f8f49e59491a9c3210b97f8277ef9bf814073883b7a324b927f00163edc27f4" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "solana-precompile-error" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68bed837597986ab0f44eea3240e2a09c09004516c27274d24450da8f9d84eb5" +dependencies = [ + "num-traits", + "solana-decode-error", +] + +[[package]] +name = "solana-precompiles" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbedabd76bfd8a718561510e88d87e94ebc575324a56b3480ee50c9cdf618fdf" +dependencies = [ + "lazy_static", + "solana-ed25519-program", + "solana-feature-set", + "solana-message", + "solana-precompile-error", + "solana-pubkey", + "solana-sdk-ids", + "solana-secp256k1-program", + "solana-secp256r1-program", +] + +[[package]] +name = "solana-presigner" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dcfaeef4597fdca40172bd1eeba1247239e61c156db05529fe31d3df889e3b8" +dependencies = [ + "solana-pubkey", + "solana-signature", + "solana-signer", +] + +[[package]] +name = "solana-program" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e3353ad06f95d4624bffc9cf01fc9f9ac4566977df6ece3175fd2119834025" +dependencies = [ + "bincode", + "blake3", + "borsh 0.10.4", + "borsh 1.5.5", + "bs58", + "bytemuck", + "console_error_panic_hook", + "console_log", + "getrandom 0.2.15", + "lazy_static", + "log", + "memoffset", + "num-bigint 0.4.6", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_derive", + "solana-account-info", + "solana-address-lookup-table-interface", + "solana-atomic-u64", + "solana-big-mod-exp", + "solana-bincode", + "solana-blake3-hasher", + "solana-borsh", + "solana-clock", + "solana-cpi", + "solana-decode-error", + "solana-define-syscall", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-example-mocks", + "solana-feature-gate-interface", + "solana-fee-calculator", + "solana-hash", + "solana-instruction", + "solana-instructions-sysvar", + "solana-keccak-hasher", + "solana-last-restart-slot", + "solana-loader-v2-interface", + "solana-loader-v3-interface", + "solana-loader-v4-interface", + "solana-message", + "solana-msg", + "solana-native-token", + "solana-nonce", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-program-option", + "solana-program-pack", + "solana-pubkey", + "solana-rent", + "solana-sanitize", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-secp256k1-recover", + "solana-serde-varint", + "solana-serialize-utils", + "solana-sha256-hasher", + "solana-short-vec", + "solana-slot-hashes", + "solana-slot-history", + "solana-stable-layout", + "solana-stake-interface", + "solana-system-interface", + "solana-sysvar", + "solana-sysvar-id", + "solana-vote-interface", + "thiserror 2.0.11", + "wasm-bindgen", +] + +[[package]] +name = "solana-program-entrypoint" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e8ac729923675be5ff5184b68f8d27bfd617b3f82bed2b2147f81fe9cda71f" +dependencies = [ + "solana-account-info", + "solana-msg", + "solana-program-error", + "solana-pubkey", +] + +[[package]] +name = "solana-program-error" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cbf136a27d9bbc680a94e289f1c07498d271685a1711e00261ceebe740c5dc" +dependencies = [ + "borsh 1.5.5", + "num-traits", + "serde", + "serde_derive", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-pubkey", +] + +[[package]] +name = "solana-program-memory" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df359a8ddd2dfc8a5b2052b26b0c7099fa74419120a2b7ac639f47da0ced7ebc" +dependencies = [ + "num-traits", + "solana-define-syscall", +] + +[[package]] +name = "solana-program-option" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f9a5b3439dbec9038519fc5d58d51d8ee57e38914ed2fc0627ab0e5e142e536" + +[[package]] +name = "solana-program-pack" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c16896889ff0eb5cee67e5eb1c5f4247e56bca4b635ebd85a163dae8ffec2ced" +dependencies = [ + "solana-program-error", +] + +[[package]] +name = "solana-pubkey" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5eb2846bcb028107c3979316501205c70fa64789214b5af85752fee61e7279" +dependencies = [ + "borsh 0.10.4", + "borsh 1.5.5", + "bs58", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "five8_const", + "getrandom 0.2.15", + "js-sys", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "solana-atomic-u64", + "solana-decode-error", + "solana-define-syscall", + "solana-sanitize", + "solana-sha256-hasher", + "wasm-bindgen", +] + +[[package]] +name = "solana-pubsub-client" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "crossbeam-channel", + "futures-util", + "log", + "reqwest", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-clock", + "solana-pubkey", + "solana-rpc-client-api", + "solana-signature", + "thiserror 2.0.11", + "tokio", + "tokio-stream", + "tokio-tungstenite 0.20.1", + "tungstenite 0.20.1", + "url", +] + +[[package]] +name = "solana-quic-client" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "async-lock", + "async-trait", + "futures", + "itertools 0.12.1", + "lazy_static", + "log", + "quinn", + "quinn-proto", + "rustls 0.23.23", + "solana-connection-cache", + "solana-keypair", + "solana-measure", + "solana-metrics", + "solana-net-utils", + "solana-pubkey", + "solana-quic-definitions", + "solana-rpc-client-api", + "solana-signer", + "solana-streamer", + "solana-tls-utils", + "solana-transaction-error", + "thiserror 2.0.11", + "tokio", +] + +[[package]] +name = "solana-quic-definitions" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8d8b557d01e61e3d73803e0a273ba3f13eb01fc9dd2a4cc54797a7f20c91f9" +dependencies = [ + "solana-keypair", +] + +[[package]] +name = "solana-rayon-threadlimit" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "lazy_static", + "num_cpus", +] + +[[package]] +name = "solana-rent" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9c0ba8a033fd38dc86270843243af7769fa0575ca61f56064aa87a825649540" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-rent-collector" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c245faddc73cac99b6b65f7e5c638b5242be70ae71cbcb11189ec4a1e6051f3" +dependencies = [ + "serde", + "serde_derive", + "solana-account", + "solana-clock", + "solana-epoch-schedule", + "solana-genesis-config", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", +] + +[[package]] +name = "solana-rent-debits" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48def7a8a9c3ae777c9d4de16a35f29510e2c8a8dd688f0ed3e3d7217aaa9e9d" +dependencies = [ + "solana-pubkey", + "solana-reward-info", +] + +[[package]] +name = "solana-reserved-account-keys" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95206c1e7567f87fed3fb5442f7f28ca066a547b0afe25f603ef17d6ca90977e" +dependencies = [ + "lazy_static", + "solana-feature-set", + "solana-pubkey", + "solana-sdk-ids", +] + +[[package]] +name = "solana-reward-info" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69c1667d87015f7b673d7633bec1b3bdc53380ef78c2eecf6927767950d5624b" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "solana-rpc-client" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bincode", + "bs58", + "indicatif", + "log", + "reqwest", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account", + "solana-account-decoder-client-types", + "solana-clock", + "solana-commitment-config", + "solana-epoch-info", + "solana-epoch-schedule", + "solana-feature-gate-interface", + "solana-hash", + "solana-instruction", + "solana-message", + "solana-pubkey", + "solana-rpc-client-api", + "solana-signature", + "solana-transaction", + "solana-transaction-error", + "solana-transaction-status-client-types", + "solana-version", + "tokio", +] + +[[package]] +name = "solana-rpc-client-api" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bs58", + "jsonrpc-core", + "reqwest", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account", + "solana-account-decoder-client-types", + "solana-clock", + "solana-commitment-config", + "solana-fee-calculator", + "solana-inflation", + "solana-inline-spl", + "solana-pubkey", + "solana-signer", + "solana-transaction-error", + "solana-transaction-status-client-types", + "solana-version", + "thiserror 2.0.11", +] + +[[package]] +name = "solana-rpc-client-nonce-utils" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "solana-account", + "solana-commitment-config", + "solana-hash", + "solana-message", + "solana-nonce", + "solana-pubkey", + "solana-rpc-client", + "solana-sdk-ids", + "thiserror 2.0.11", +] + +[[package]] +name = "solana-sanitize" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b9c8488d45d48d98e2aca7cb61bc1fc7e3a7e14aac48efb88b0ddd08fb785ae" + +[[package]] +name = "solana-sdk" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7f31a3861541f053cb770049f9727f3e2eab18940c21e289d2db8bfc7082c41" +dependencies = [ + "bincode", + "bs58", + "getrandom 0.1.16", + "js-sys", + "serde", + "serde_json", + "solana-account", + "solana-bn254", + "solana-client-traits", + "solana-cluster-type", + "solana-commitment-config", + "solana-compute-budget-interface", + "solana-decode-error", + "solana-derivation-path", + "solana-ed25519-program", + "solana-epoch-info", + "solana-epoch-rewards-hasher", + "solana-feature-set", + "solana-fee-structure", + "solana-genesis-config", + "solana-hard-forks", + "solana-inflation", + "solana-instruction", + "solana-keypair", + "solana-message", + "solana-native-token", + "solana-nonce-account", + "solana-offchain-message", + "solana-packet", + "solana-poh-config", + "solana-precompile-error", + "solana-precompiles", + "solana-presigner", + "solana-program", + "solana-program-memory", + "solana-pubkey", + "solana-quic-definitions", + "solana-rent-collector", + "solana-rent-debits", + "solana-reserved-account-keys", + "solana-reward-info", + "solana-sanitize", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-secp256k1-program", + "solana-secp256k1-recover", + "solana-secp256r1-program", + "solana-seed-derivable", + "solana-seed-phrase", + "solana-serde", + "solana-serde-varint", + "solana-short-vec", + "solana-shred-version", + "solana-signature", + "solana-signer", + "solana-system-transaction", + "solana-time-utils", + "solana-transaction", + "solana-transaction-context", + "solana-transaction-error", + "solana-validator-exit", + "thiserror 2.0.11", + "wasm-bindgen", +] + +[[package]] +name = "solana-sdk-ids" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6776348ff4384ceb2bca7b04a22bec4710e2551f42e2bd84d14340892d4a43db" +dependencies = [ + "solana-pubkey", +] + +[[package]] +name = "solana-sdk-macro" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cedd8618f65460ede61644d863b8fa29059b7f4392ed2b6ac737d432b5fbe1f6" +dependencies = [ + "bs58", + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "solana-secp256k1-program" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4163a54e579e2d50f5c38cde401d4efef2bbcacfb7e59dcfb6a7b82a0f02fb60" +dependencies = [ + "bincode", + "digest 0.10.7", + "libsecp256k1", + "serde", + "serde_derive", + "sha3", + "solana-feature-set", + "solana-instruction", + "solana-precompile-error", + "solana-sdk-ids", +] + +[[package]] +name = "solana-secp256k1-recover" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e68ffe614d1adfce894ed8c7877e40d43507a7254b1eb89cfbeb479b8d10b1c" +dependencies = [ + "borsh 1.5.5", + "libsecp256k1", + "solana-define-syscall", + "thiserror 2.0.11", +] + +[[package]] +name = "solana-secp256r1-program" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9190530ab9c16fe118837b2cd4905f64677bc536dd1193829ea39793448c667" +dependencies = [ + "bytemuck", + "openssl", + "solana-feature-set", + "solana-instruction", + "solana-precompile-error", + "solana-sdk-ids", +] + +[[package]] +name = "solana-seed-derivable" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622328288b94203f2318ff920cc0f9d22d2de381d3bbc709b227011de27a35e9" +dependencies = [ + "solana-derivation-path", +] + +[[package]] +name = "solana-seed-phrase" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777a3e5f685064f7775acdf25af35d62089faa5dfe0d9825da2988a3fc6b321d" +dependencies = [ + "hmac 0.12.1", + "pbkdf2 0.11.0", + "sha2 0.10.8", +] + +[[package]] +name = "solana-serde" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "247317d6750e2b83dda5a26f7ee4ed8b0dec1713170abb45c2a45194384bf72b" +dependencies = [ + "serde", +] + +[[package]] +name = "solana-serde-varint" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2df892c94d1d120fe12aebb05130edba58bde445607ba872cd5c9ae4f348f516" +dependencies = [ + "serde", +] + +[[package]] +name = "solana-serialize-utils" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e47c29ddb0b6678f669304a0f74458931c4413f4f62d45a047a14d007f0dfd3" +dependencies = [ + "solana-instruction", + "solana-pubkey", + "solana-sanitize", +] + +[[package]] +name = "solana-sha256-hasher" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e628c2ac45e6896dfd1de1fa8891ad77b6b97209c0732631904e41798a529e3d" +dependencies = [ + "sha2 0.10.8", + "solana-define-syscall", + "solana-hash", +] + +[[package]] +name = "solana-short-vec" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e98f50b5f03b56077bfe3956287765b1cd2b220d6a8e3c0b5b6993011cea239" +dependencies = [ + "serde", +] + +[[package]] +name = "solana-shred-version" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd33639ce0640e11e5525c13661fc0e4ddde4c033fa8bd364e2ea039511944a" +dependencies = [ + "solana-hard-forks", + "solana-hash", + "solana-sha256-hasher", +] + +[[package]] +name = "solana-signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a549905698c91340f66e44926e774681abb7e4eecb4a85fe30a4a7a4ef9ba642" +dependencies = [ + "bs58", + "ed25519-dalek", + "rand 0.8.5", + "serde", + "serde-big-array", + "serde_derive", + "solana-sanitize", +] + +[[package]] +name = "solana-signer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58b85384f5de9c78cc05bc14a93facddb3f35b6d4dd96b66b3d11267b2efc066" +dependencies = [ + "solana-pubkey", + "solana-signature", + "solana-transaction-error", +] + +[[package]] +name = "solana-slot-hashes" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f64dff66ac8e2ddcd8228678b7bc81b7a799cd23e010b34bf6b72887016f838e" +dependencies = [ + "serde", + "serde_derive", + "solana-hash", + "solana-sdk-ids", + "solana-sysvar-id", +] + +[[package]] +name = "solana-slot-history" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2568f681cb16ed4db3abfeb1e9ed1e47a0e3dbe0419a730c7bcfd68030747a8" +dependencies = [ + "bv", + "serde", + "serde_derive", + "solana-sdk-ids", + "solana-sysvar-id", +] + +[[package]] +name = "solana-stable-layout" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9647ffca7c9a4d9eee626851fdd1ee1439fcef33228c4c86c7a6f3332b2f9bb9" +dependencies = [ + "solana-instruction", + "solana-pubkey", +] + +[[package]] +name = "solana-stake-interface" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5269e89fde216b4d7e1d1739cf5303f8398a1ff372a81232abbee80e554a838c" +dependencies = [ + "borsh 0.10.4", + "borsh 1.5.5", + "num-traits", + "serde", + "serde_derive", + "solana-clock", + "solana-cpi", + "solana-decode-error", + "solana-instruction", + "solana-program-error", + "solana-pubkey", + "solana-system-interface", + "solana-sysvar-id", +] + +[[package]] +name = "solana-streamer" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "async-channel", + "bytes", + "crossbeam-channel", + "dashmap", + "futures", + "futures-util", + "governor", + "histogram", + "indexmap 2.7.1", + "itertools 0.12.1", + "libc", + "log", + "nix", + "pem", + "percentage", + "quinn", + "quinn-proto", + "rand 0.8.5", + "rustls 0.23.23", + "smallvec", + "socket2", + "solana-keypair", + "solana-measure", + "solana-metrics", + "solana-net-utils", + "solana-packet", + "solana-perf", + "solana-pubkey", + "solana-quic-definitions", + "solana-signature", + "solana-signer", + "solana-time-utils", + "solana-tls-utils", + "solana-transaction-error", + "solana-transaction-metrics-tracker", + "thiserror 2.0.11", + "tokio", + "tokio-util", + "x509-parser", +] + +[[package]] +name = "solana-system-interface" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d7c18cb1a91c6be5f5a8ac9276a1d7c737e39a21beba9ea710ab4b9c63bc90" +dependencies = [ + "js-sys", + "num-traits", + "serde", + "serde_derive", + "solana-decode-error", + "solana-instruction", + "solana-pubkey", + "wasm-bindgen", +] + +[[package]] +name = "solana-system-transaction" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad50e7d25b91189edd0827ba51bdac9eba1163a6e4b2c32504b59222c2d187f7" +dependencies = [ + "solana-hash", + "solana-keypair", + "solana-message", + "solana-pubkey", + "solana-signer", + "solana-system-interface", + "solana-transaction", +] + +[[package]] +name = "solana-sysvar" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e68c122b502fd9c5a0584af938d62f2cbfbdd60f22d3ecf40d3c8a23da5e563c" +dependencies = [ + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "lazy_static", + "serde", + "serde_derive", + "solana-account-info", + "solana-clock", + "solana-define-syscall", + "solana-epoch-rewards", + "solana-epoch-schedule", + "solana-fee-calculator", + "solana-hash", + "solana-instruction", + "solana-instructions-sysvar", + "solana-last-restart-slot", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-pubkey", + "solana-rent", + "solana-sanitize", + "solana-sdk-ids", + "solana-sdk-macro", + "solana-slot-hashes", + "solana-slot-history", + "solana-stake-interface", + "solana-sysvar-id", +] + +[[package]] +name = "solana-sysvar-id" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df06917586e1eff97754d610fe59972ff9cb181c8c6112a89b7ca68d88977a00" +dependencies = [ + "solana-pubkey", + "solana-sdk-ids", +] + +[[package]] +name = "solana-thin-client" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "bincode", + "log", + "rayon", + "solana-account", + "solana-client-traits", + "solana-clock", + "solana-commitment-config", + "solana-connection-cache", + "solana-epoch-info", + "solana-hash", + "solana-instruction", + "solana-keypair", + "solana-message", + "solana-pubkey", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-signature", + "solana-signer", + "solana-system-interface", + "solana-transaction", + "solana-transaction-error", +] + +[[package]] +name = "solana-time-utils" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1da442f9f36c711d49d1f5059da8c55b8a9bed03d26396646e82932a06fb53a" + +[[package]] +name = "solana-tls-utils" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "rustls 0.23.23", + "solana-keypair", + "solana-pubkey", + "solana-signer", + "x509-parser", +] + +[[package]] +name = "solana-tpu-client" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "async-trait", + "bincode", + "futures-util", + "indexmap 2.7.1", + "indicatif", + "log", + "rayon", + "solana-client-traits", + "solana-clock", + "solana-commitment-config", + "solana-connection-cache", + "solana-epoch-info", + "solana-measure", + "solana-message", + "solana-net-utils", + "solana-pubkey", + "solana-pubsub-client", + "solana-quic-definitions", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-signature", + "solana-signer", + "solana-transaction", + "solana-transaction-error", + "thiserror 2.0.11", + "tokio", +] + +[[package]] +name = "solana-transaction" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "075b7c2b50c1ce9a1d81802d39673d0b039f5dc5d2a018dfc07ae60b7f81f988" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-bincode", + "solana-feature-set", + "solana-hash", + "solana-instruction", + "solana-keypair", + "solana-message", + "solana-precompiles", + "solana-pubkey", + "solana-reserved-account-keys", + "solana-sanitize", + "solana-sdk-ids", + "solana-short-vec", + "solana-signature", + "solana-signer", + "solana-system-interface", + "solana-transaction-error", + "wasm-bindgen", +] + +[[package]] +name = "solana-transaction-context" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "717bb0e0ccfd2d16c63cc5270ee75e67e6741de7d4123494165e225c59d9d187" +dependencies = [ + "bincode", + "serde", + "serde_derive", + "solana-account", + "solana-instruction", + "solana-pubkey", + "solana-rent", + "solana-signature", +] + +[[package]] +name = "solana-transaction-error" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74cd8bc1bb3886d9565856d29db7d8be79a106f75c82da5c906ba8312e14298c" +dependencies = [ + "serde", + "serde_derive", + "solana-instruction", + "solana-sanitize", +] + +[[package]] +name = "solana-transaction-metrics-tracker" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "base64 0.22.1", + "bincode", + "lazy_static", + "log", + "rand 0.8.5", + "solana-packet", + "solana-perf", + "solana-short-vec", + "solana-signature", +] + +[[package]] +name = "solana-transaction-status-client-types" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "base64 0.22.1", + "bincode", + "bs58", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-commitment-config", + "solana-message", + "solana-reward-info", + "solana-signature", + "solana-transaction", + "solana-transaction-context", + "solana-transaction-error", + "thiserror 2.0.11", +] + +[[package]] +name = "solana-udp-client" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "async-trait", + "solana-connection-cache", + "solana-keypair", + "solana-net-utils", + "solana-streamer", + "solana-transaction-error", + "thiserror 2.0.11", + "tokio", +] + +[[package]] +name = "solana-validator-exit" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d61992deaa06427057f910ca9a591f386e7b3a34465a3cae8be98e55b26ba8f" + +[[package]] +name = "solana-version" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "semver", + "serde", + "serde_derive", + "solana-feature-set", + "solana-sanitize", + "solana-serde-varint", +] + +[[package]] +name = "solana-vote-interface" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe6036f3a0748d039404998090915273b11379034656a132dd41cceb05abf94" +dependencies = [ + "bincode", + "num-derive", + "num-traits", + "serde", + "serde_derive", + "solana-clock", + "solana-decode-error", + "solana-hash", + "solana-instruction", + "solana-pubkey", + "solana-rent", + "solana-sdk-ids", + "solana-serde-varint", + "solana-serialize-utils", + "solana-short-vec", + "solana-system-interface", +] + +[[package]] +name = "solana-zk-token-sdk" +version = "2.2.0" +source = "git+https://github.com/anza-xyz/agave.git?branch=v2.2#f5c162cbfcc03985f63c0603086194277124e88b" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "itertools 0.12.1", + "lazy_static", + "merlin", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha3", + "solana-curve25519", + "solana-derivation-path", + "solana-instruction", + "solana-pubkey", + "solana-sdk-ids", + "solana-seed-derivable", + "solana-seed-phrase", + "solana-signature", + "solana-signer", + "subtle", + "thiserror 2.0.11", + "zeroize", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlx" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" +dependencies = [ + "bytes", + "crc", + "crossbeam-queue", + "either", + "event-listener 5.4.0", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashbrown 0.15.2", + "hashlink", + "indexmap 2.7.1", + "log", + "memchr", + "once_cell", + "percent-encoding", + "serde", + "serde_json", + "sha2 0.10.8", + "smallvec", + "thiserror 2.0.11", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.98", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" +dependencies = [ + "dotenvy", + "either", + "heck 0.5.0", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2 0.10.8", + "sqlx-core", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", + "syn 2.0.98", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.8.0", + "byteorder", + "bytes", + "crc", + "digest 0.10.7", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac 0.12.1", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.11", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" +dependencies = [ + "atoi", + "base64 0.22.1", + "bitflags 2.8.0", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-util", + "hex", + "hkdf", + "hmac 0.12.1", + "home", + "itoa", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2 0.10.8", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror 2.0.11", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "serde_urlencoded", + "sqlx-core", + "tracing", + "url", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "task-local-extensions" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba323866e5d033818e3240feeb9f7db2c4296674e4d9e16b97b7bf8f490434e8" +dependencies = [ + "pin-utils", +] + +[[package]] +name = "tempfile" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +dependencies = [ + "cfg-if", + "fastrand", + "getrandom 0.3.1", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" +dependencies = [ + "rustls 0.23.23", + "tokio", +] + +[[package]] +name = "tokio-socks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +dependencies = [ + "either", + "futures-util", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", + "tungstenite 0.20.1", + "webpki-roots 0.25.4", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "rustls 0.23.23", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.1", + "tungstenite 0.24.0", + "webpki-roots 0.26.8", +] + +[[package]] +name = "tokio-util" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" +dependencies = [ + "indexmap 2.7.1", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 0.2.12", + "httparse", + "log", + "rand 0.8.5", + "rustls 0.21.12", + "sha1", + "thiserror 1.0.69", + "url", + "utf-8", + "webpki-roots 0.24.0", +] + +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.2.0", + "httparse", + "log", + "rand 0.8.5", + "rustls 0.23.23", + "rustls-pki-types", + "sha1", + "thiserror 1.0.69", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-ident" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" + +[[package]] +name = "unicode-normalization" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "uriparse" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" +dependencies = [ + "fnv", + "lazy_static", +] + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.98", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "0.26.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09aed61f5e8d2c18344b3faa33a4c837855fe56642757754775548fee21386c4" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webpki-roots" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888" +dependencies = [ + "rustls-webpki 0.101.7", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "webpki-roots" +version = "0.26.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "whoami" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +dependencies = [ + "redox_syscall", + "wasite", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59690dea168f2198d1a3b0cac23b8063efcd11012f10ae4698f284808c8ef603" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.8.0", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs", + "base64 0.13.1", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", + "synstructure 0.13.1", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", + "synstructure 0.13.1", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/dephy-vending_machine-examples/Cargo.toml b/dephy-vending_machine-examples/Cargo.toml new file mode 100644 index 0000000..b440d8f --- /dev/null +++ b/dephy-vending_machine-examples/Cargo.toml @@ -0,0 +1,36 @@ +[workspace] +resolver = "2" +members = [ + "balance-payment-sdk", + "examples/*", +] + +[workspace.package] +license = "MIT" + +[workspace.dependencies] +solana-client = { version = "2.2.0", git = "https://github.com/anza-xyz/agave.git", branch = "v2.2" } +solana-program = "2.2.0" +solana-sdk = { version = "2.2.0", features = ["openssl-vendored"] } +solana-zk-token-sdk = { version = "2.2.0", git = "https://github.com/anza-xyz/agave.git", branch = "v2.2" } + +arrayref = "0.3.9" +borsh = "0.10.4" +curve25519-dalek = "4.1.3" +num-derive = "0.4.2" +num-traits = "0.2.19" +serde = "1.0.217" +serde_json = "1.0.137" +serde_with = "3.12.0" +sha2 = "0.10.8" +thiserror = "2.0.11" +tracing = "0.1.41" + +clap = "4.5.29" +futures = "0.3.31" +nostr = "0.38.0" +nostr-sdk = "0.38.0" +tokio = "1.43.0" +tracing-subscriber = "0.3.19" + +dephy-balance-payment-sdk = { version = "0.1.0", path = "./balance-payment-sdk" } diff --git a/dephy-vending_machine-examples/MIT-LICENSE b/dephy-vending_machine-examples/MIT-LICENSE new file mode 100644 index 0000000..1784699 --- /dev/null +++ b/dephy-vending_machine-examples/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) DEPHY TECHNOLOGY PTE. LTD. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/dephy-vending_machine-examples/README.md b/dephy-vending_machine-examples/README.md new file mode 100644 index 0000000..18278b1 --- /dev/null +++ b/dephy-vending_machine-examples/README.md @@ -0,0 +1,42 @@ +# DePHY vending machine examples + +This is a vending machine showcase for DePHY Messaging Layer. + +## Online demo + +The program has deployed to Solana devnet, address: `GguVKxU88NUe3GLtns7Uaa6a8Pjb9USKq3WD1rjZnPS9` + +See for the dApp + +## How it works + +![](./doc/architecture.png) + +## Repo contents + +- [Solana program and dApp](./balance-payment) + - [dApp](./balance-payment/app) +- [Pre-generated program Rust SDK](./balance-payment-sdk) +- Examples + - [DeCharge](./examples/decharge-controller) + - [Gacha](./examples/gacha-controller) + +## Run from source + +1. Run DePHY vending machine workers by: `docker compose up` +2. [Deploy the Solana program and run the dApp](./balance-payment/README.md) + +## TODO + +- Build a scripts to quick deploy a local demo +- Rename DeCharge things to vending machine +- Rich docs + +## Future works + +- Use an offchain account book to ensure the process transactionality +- Indexer and a dashboard dAPP for showing order history + +## License + +MIT diff --git a/dephy-vending_machine-examples/balance-payment-sdk/Cargo.lock b/dephy-vending_machine-examples/balance-payment-sdk/Cargo.lock new file mode 100644 index 0000000..a4de112 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/Cargo.lock @@ -0,0 +1,5616 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "Inflector" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" +dependencies = [ + "lazy_static", + "regex", +] + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle", + "zeroize", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom 0.2.15", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint 0.4.6", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint 0.4.6", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint 0.4.6", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "ascii" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" + +[[package]] +name = "asn1-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6fd5ddaf0351dff5b8da21b2fb4ff8e08ddd02857f0bf69c47639106c0fff0" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "726535892e8eae7e70657b4c8ea93d26b8553afb1ce617caee529ef96d7dee6c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "synstructure 0.12.6", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2777730b2039ac0f95f093556e61b6d26cebed5393ca6f152717777cec3a42ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-compression" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df895a515f70646414f4b45c0b79082783b80552b373a68283012928df56f522" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener 5.4.0", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-trait" +version = "0.1.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[package]] +name = "balance-payment-sdk" +version = "0.1.0" +dependencies = [ + "arrayref", + "borsh 0.10.4", + "curve25519-dalek 4.1.3", + "num-derive", + "num-traits", + "serde", + "serde_json", + "serde_with", + "sha2 0.10.8", + "solana-client", + "solana-program", + "solana-sdk", + "solana-zk-token-sdk", + "thiserror 2.0.11", + "tracing", +] + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +dependencies = [ + "serde", +] + +[[package]] +name = "blake3" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "borsh" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" +dependencies = [ + "borsh-derive 0.10.4", + "hashbrown 0.13.2", +] + +[[package]] +name = "borsh" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc" +dependencies = [ + "borsh-derive 1.5.5", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8b668d39970baad5356d7c83a86fee3a539e6f93bf6764c97368243e17a0487" +dependencies = [ + "once_cell", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "brotli" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74fa05ad7d803d413eb8380983b092cbbaf9a85f151b871360e7b00cd7060b37" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" + +[[package]] +name = "caps" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190baaad529bcfbde9e1a19022c42781bdb6ff9de25721abdb8fd98c0807730b" +dependencies = [ + "libc", + "thiserror 1.0.69", +] + +[[package]] +name = "cc" +version = "1.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" +dependencies = [ + "jobserver", + "libc", + "shlex", +] + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cfg_eval" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45565fc9416b9896014f5732ac776f810ee53a66730c17e4020c3ec064a8f88f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets 0.52.6", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "combine" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" +dependencies = [ + "ascii", + "byteorder", + "either", + "memchr", + "unreachable", +] + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys 0.59.0", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest 0.10.7", + "fiat-crypto", + "rand_core 0.6.4", + "rustc_version", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.96", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e60eed09d8c01d3cee5b7d30acb059b76614c918fa0f992e0dd6eeb10daad6f" + +[[package]] +name = "der-parser" +version = "8.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint 0.4.6", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derivation-path" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "dlopen2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cbae11b3de8fce2a456e8ea3dada226b35fe791f0dc1d360c0941f0bb681f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "eager" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe71d579d1812060163dff96056261deb5bf6729b100fa2e36a68b9649ba3d3" + +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.0", + "ed25519", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-dalek-bip32" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" +dependencies = [ + "derivation-path", + "ed25519-dalek", + "hmac 0.12.1", + "sha2 0.10.8", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-iterator" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fd242f399be1da0a5354aa462d57b4ab2b4ee0683cc552f7c007d2d12d36e94" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3e4e0dd3673c1139bf041f3008816d9cf2946bbfac2945c09e523b8d7b05b2" +dependencies = [ + "event-listener 5.4.0", + "pin-project-lite", +] + +[[package]] +name = "feature-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "five8_const" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b4f62f0f8ca357f93ae90c8c2dd1041a1f665fde2f889ea9b1787903829015" +dependencies = [ + "five8_core", +] + +[[package]] +name = "five8_core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94474d15a76982be62ca8a39570dccce148d98c238ebb7408b0a21b2c4bdddc4" + +[[package]] +name = "flate2" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "serde", + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ebd34e35c46e00bb73e81363248d627782724609fe1b6396f553f68fe3862e" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "governor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" +dependencies = [ + "cfg-if", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand 0.8.5", + "smallvec", + "spinning_top", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.7.1", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "histogram" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12cb882ccb290b8646e554b157ab0b71e64e8d5bef775cd66b6531e52d302669" + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http", + "hyper", + "rustls 0.21.12", + "tokio", + "tokio-rustls", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", + "serde", +] + +[[package]] +name = "indicatif" +version = "0.17.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf675b85ed934d3c67b5c5469701eec7db22689d0a2139d856e0925fa28b281" +dependencies = [ + "console", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine 4.6.7", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "jsonrpc-core" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f7f76aef2d054868398427f6c54943cf3d1caa9a7ec7d0c38d69df97a965eb" +dependencies = [ + "futures", + "futures-executor", + "futures-util", + "log", + "serde", + "serde_derive", + "serde_json", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libsecp256k1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "litemap" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + +[[package]] +name = "nix" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +dependencies = [ + "bitflags 2.8.0", + "cfg-if", + "cfg_aliases", + "libc", + "memoffset", +] + +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + +[[package]] +name = "num" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8536030f9fea7127f841b45bb6243b27255787fb4eb83958aa1ef9d2fdc0c36" +dependencies = [ + "num-bigint 0.2.6", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "090c7f9998ee0ff65aa5b723e4009f7b217707f1fb5ea551329cc4d6231fb304" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-bigint 0.2.6", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bedf36ffb6ba96c2eb7144ef6270557b52e54b20c0a8e1eb2ff99a6c6959bff" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags 2.8.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-src" +version = "300.4.1+3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faa4eac4138c62414b5622d1b31c5c304f34b406b013c079c2bbc652fdd6678c" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "pem" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" +dependencies = [ + "base64 0.13.1", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "percentage" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd23b938276f14057220b707937bcb42fa76dda7560e57a2da30cb52d557937" +dependencies = [ + "num", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "qstring" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "quanta" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bd1fe6824cea6538803de3ff1bc0cf3949024db3d43c9643024bfb33a807c0e" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi 0.11.0+wasi-snapshot-preview1", + "web-sys", + "winapi", +] + +[[package]] +name = "quinn" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.21", + "socket2", + "thiserror 2.0.11", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" +dependencies = [ + "bytes", + "getrandom 0.2.15", + "rand 0.8.5", + "ring", + "rustc-hash", + "rustls 0.23.21", + "rustls-pki-types", + "rustls-platform-verifier", + "slab", + "thiserror 2.0.11", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-cpuid" +version = "11.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6928fa44c097620b706542d428957635951bade7143269085389d42c8a4927e" +dependencies = [ + "bitflags 2.8.0", +] + +[[package]] +name = "rayon" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags 2.8.0", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.11.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" +dependencies = [ + "async-compression", + "base64 0.21.7", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-rustls", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-rustls", + "tokio-util", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots 0.25.4", + "winreg", +] + +[[package]] +name = "reqwest-middleware" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a735987236a8e238bf0296c7e351b999c188ccc11477f311b82b55c93984216" +dependencies = [ + "anyhow", + "async-trait", + "http", + "reqwest", + "serde", + "task-local-extensions", + "thiserror 1.0.69", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.15", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.23.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki 0.102.8", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile 2.2.0", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "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]] +name = "rustls-pki-types" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +dependencies = [ + "web-time", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c7dc240fec5517e6c4eab3310438636cfe6391dfc345ba013109909a90d136" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls 0.23.21", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki 0.102.8", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.102.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "scroll" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04c565b551bafbef4157586fa379538366e4385d42082f255bfd96e4fe8519da" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.8.0", + "core-foundation", + "core-foundation-sys", + "libc", + "num-bigint 0.4.6", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "serde_json" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.7.1", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "solana-account" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8557558040a6bf34101ea0ded1647bafc21c2a9ea0913034fa6794a304ba6791" +dependencies = [ + "bincode", + "serde", + "serde_bytes", + "serde_derive", + "solana-instruction", + "solana-program", +] + +[[package]] +name = "solana-account-decoder" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2353887223851d07071e790a6508d8df61032a5e01bb6f990d7abe7f58dde3aa" +dependencies = [ + "Inflector", + "base64 0.22.1", + "bincode", + "bs58", + "bv", + "lazy_static", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-config-program", + "solana-sdk", + "spl-token", + "spl-token-2022", + "spl-token-group-interface", + "spl-token-metadata-interface", + "thiserror 1.0.69", + "zstd", +] + +[[package]] +name = "solana-account-decoder-client-types" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435bb722c456f78dd3ac33a1b4641c46d5d41de5b072422ae5b0dc9f486c0928" +dependencies = [ + "base64 0.22.1", + "bs58", + "serde", + "serde_derive", + "serde_json", + "solana-account", + "solana-pubkey", + "zstd", +] + +[[package]] +name = "solana-account-info" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abeb32e8dbead1f920a919d8c781fe058cf657313aa237566fa812d2288f2aab" +dependencies = [ + "bincode", + "serde", + "solana-program-error", + "solana-program-memory", + "solana-pubkey", +] + +[[package]] +name = "solana-atomic-u64" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ceb7242711300b8d67933a3cd1c9b2cd7c4e98de529356ecddf340c98c457d" +dependencies = [ + "parking_lot", +] + +[[package]] +name = "solana-bincode" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e154567b6846f4721c713afdd14c56892800fb940793ef529a68d6db6cf1beef" +dependencies = [ + "bincode", + "serde", + "solana-instruction", +] + +[[package]] +name = "solana-bn254" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c42ad3282999ef7df859e7ed03a6e6a4187ff4931f9814ddcd0477dba2be15" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "bytemuck", + "solana-program", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-borsh" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b2428671e99134c97990d2b466c33779f785376b7934e6bddb635929c54208f" +dependencies = [ + "borsh 0.10.4", + "borsh 1.5.5", +] + +[[package]] +name = "solana-client" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73d3a06371c4b63efa8d2dde9890b658891943807c529144eac6d2345538077d" +dependencies = [ + "async-trait", + "bincode", + "dashmap", + "futures", + "futures-util", + "indexmap 2.7.1", + "indicatif", + "log", + "quinn", + "rayon", + "solana-connection-cache", + "solana-measure", + "solana-pubsub-client", + "solana-quic-client", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-rpc-client-nonce-utils", + "solana-sdk", + "solana-streamer", + "solana-thin-client", + "solana-tpu-client", + "solana-udp-client", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "solana-clock" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d639043cefcd061c31a342364adcb204406ebbd91ef86dfde88b74352b688cf" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-compute-budget" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6c885192c0afe6f7beac13e1c8eb51ce36bc60e8f0b7631f9cbf72d8ca6aa03" +dependencies = [ + "solana-sdk", +] + +[[package]] +name = "solana-config-program" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "056ce3a28f5e22677e0db1fc976294041571c4d471a752bfc9f1b06f8828c488" +dependencies = [ + "bincode", + "chrono", + "serde", + "serde_derive", + "solana-log-collector", + "solana-program-runtime", + "solana-sdk", + "solana-short-vec", +] + +[[package]] +name = "solana-connection-cache" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52912ec1eb7b40af2a81269d0bb2cefba01f303383cba32067d0dc5020556e38" +dependencies = [ + "async-trait", + "bincode", + "crossbeam-channel", + "futures-util", + "indexmap 2.7.1", + "log", + "rand 0.8.5", + "rayon", + "solana-measure", + "solana-metrics", + "solana-sdk", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "solana-cpi" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b87b387931f41422be3d82190e29c8414bbb4e8517dd94afb838012260d7a60" +dependencies = [ + "solana-account-info", + "solana-define-syscall", + "solana-instruction", + "solana-program-error", + "solana-pubkey", + "solana-stable-layout", +] + +[[package]] +name = "solana-curve25519" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71b91a6c7db7874ab0721ba2ad49c34614c6af5bfa1a02f18ee471d28416b1fc" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "solana-program", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-decode-error" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64b93163519c0b7419d3ac206207594d4b43e00267496996b898345ff3b31ed1" +dependencies = [ + "num-traits", +] + +[[package]] +name = "solana-define-syscall" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d1b215d56d29f71782df6880d71b5a46cf9a4035046414488c7de6906899ba" + +[[package]] +name = "solana-derivation-path" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31edf5d285689b469471a1a0200f0c9196be7df155860bd83dfd735439172bd" +dependencies = [ + "derivation-path", + "qstring", + "uriparse", +] + +[[package]] +name = "solana-epoch-schedule" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88aa6588f178c32258eb616ef1428f2c86beae370d6486843313f6320e055190" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-feature-set" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1736c5f6cb5d65e684a1daf425dd1479849e0793ffe877feedb602642ee5deb0" +dependencies = [ + "lazy_static", + "solana-clock", + "solana-epoch-schedule", + "solana-hash", + "solana-pubkey", + "solana-sha256-hasher", +] + +[[package]] +name = "solana-fee-calculator" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ef28a47c3fcfd4ef8b19468531e32a431f6589f359cdbb927fc5e7fb859413" +dependencies = [ + "log", + "serde", + "serde_derive", +] + +[[package]] +name = "solana-hash" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad865143587f6173d0bd15ec66b749fd2682c865467ffd2bb725705e33f0c8fa" +dependencies = [ + "borsh 1.5.5", + "bs58", + "bytemuck", + "bytemuck_derive", + "js-sys", + "serde", + "serde_derive", + "solana-atomic-u64", + "solana-sanitize", + "wasm-bindgen", +] + +[[package]] +name = "solana-inflation" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a205cb59db7fa1afc89ad5d960ac5afb997ba231cdc943451811746c84b7776d" +dependencies = [ + "serde", + "serde_derive", +] + +[[package]] +name = "solana-inline-spl" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47d825ad3f7d3eede036d2c3b11eb385912eb3e01872bc98901802f942eab8a" +dependencies = [ + "bytemuck", + "solana-pubkey", +] + +[[package]] +name = "solana-instruction" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af795f16bef3ae76e97978e35724ea88d2b9eba67a9e233adf48ccefeaa6e6b8" +dependencies = [ + "bincode", + "borsh 1.5.5", + "getrandom 0.2.15", + "js-sys", + "num-traits", + "serde", + "serde_derive", + "solana-define-syscall", + "solana-pubkey", + "wasm-bindgen", +] + +[[package]] +name = "solana-last-restart-slot" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f88c8171167f1fd4ef1e5a083fd0e8f35ac60aacd1ffe163a1ef7053a28524be" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-log-collector" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7922b879e4c03e00bf6ed21b1f8579ac71f6743d95c22306bd1ba8994e4f90e8" +dependencies = [ + "log", +] + +[[package]] +name = "solana-measure" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13208871c6d000a0c7b7546ae605934f5eda3745f80f6926da1b6097c08f2de2" + +[[package]] +name = "solana-metrics" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555986e126fe32ad94217c5d87c94f79b7f13abf96ef9d8de20dacbcf1c407e5" +dependencies = [ + "crossbeam-channel", + "gethostname", + "lazy_static", + "log", + "reqwest", + "solana-sdk", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-msg" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aefec09cb47fb67b8f8c448e03491d4148c1749f27dcb74d1cfae6337695f94" +dependencies = [ + "solana-define-syscall", +] + +[[package]] +name = "solana-native-token" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81520eff9f776e62faa36a07250fcc467e54ca31ca9c87ab566a88b2f2691c05" + +[[package]] +name = "solana-net-utils" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b409b10fee2d0cbb2a721fa3ce7d7f6f32e0d3ae1f5807b1d6bc91d75970c72" +dependencies = [ + "bincode", + "crossbeam-channel", + "log", + "nix", + "rand 0.8.5", + "serde", + "serde_derive", + "socket2", + "solana-sdk", + "tokio", + "url", +] + +[[package]] +name = "solana-packet" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8c6e8a2cb0839ef49d8c6e34e89a5bc5ed97da855bf49528bae8c57eb39ed" +dependencies = [ + "bincode", + "bitflags 2.8.0", + "cfg_eval", + "serde", + "serde_derive", + "serde_with", +] + +[[package]] +name = "solana-perf" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fa10dd492bee710d0e231a3ff48c52d6e24f5339d97decaf1f0ddbde996f834" +dependencies = [ + "ahash", + "bincode", + "bv", + "caps", + "curve25519-dalek 4.1.3", + "dlopen2", + "fnv", + "lazy_static", + "libc", + "log", + "nix", + "rand 0.8.5", + "rayon", + "serde", + "solana-metrics", + "solana-rayon-threadlimit", + "solana-sdk", + "solana-short-vec", + "solana-vote-program", +] + +[[package]] +name = "solana-precompile-error" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83c01aefc15c451b4f573c1e4552f34ee8af53db285ee2f7ece17ef8b70d6c0a" +dependencies = [ + "num-traits", + "solana-decode-error", +] + +[[package]] +name = "solana-program" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d3a72c5eafd348bc5e5b731b40ad8dfde3023632e34e5ca9e52a655266ffae7" +dependencies = [ + "base64 0.22.1", + "bincode", + "bitflags 2.8.0", + "blake3", + "borsh 0.10.4", + "borsh 1.5.5", + "bs58", + "bv", + "bytemuck", + "bytemuck_derive", + "console_error_panic_hook", + "console_log", + "curve25519-dalek 4.1.3", + "five8_const", + "getrandom 0.2.15", + "js-sys", + "lazy_static", + "log", + "memoffset", + "num-bigint 0.4.6", + "num-derive", + "num-traits", + "parking_lot", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_derive", + "sha2 0.10.8", + "sha3", + "solana-account-info", + "solana-atomic-u64", + "solana-bincode", + "solana-borsh", + "solana-clock", + "solana-cpi", + "solana-decode-error", + "solana-define-syscall", + "solana-epoch-schedule", + "solana-fee-calculator", + "solana-hash", + "solana-instruction", + "solana-last-restart-slot", + "solana-msg", + "solana-native-token", + "solana-program-entrypoint", + "solana-program-error", + "solana-program-memory", + "solana-program-option", + "solana-program-pack", + "solana-pubkey", + "solana-rent", + "solana-sanitize", + "solana-sdk-macro", + "solana-secp256k1-recover", + "solana-serde-varint", + "solana-serialize-utils", + "solana-sha256-hasher", + "solana-short-vec", + "solana-slot-hashes", + "solana-slot-history", + "solana-stable-layout", + "solana-sysvar-id", + "solana-transaction-error", + "thiserror 1.0.69", + "wasm-bindgen", +] + +[[package]] +name = "solana-program-entrypoint" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "269ccabf1f3aff504a97aca0f8b72e6d3e1b7fb621cc18a2d21a28b17d52e112" +dependencies = [ + "solana-account-info", + "solana-msg", + "solana-program-error", + "solana-pubkey", +] + +[[package]] +name = "solana-program-error" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02f7a81eeb5c3d44b2953c46215af390ca2951a0b8069836ffbf3d368b012b35" +dependencies = [ + "borsh 1.5.5", + "num-traits", + "serde", + "serde_derive", + "solana-decode-error", + "solana-instruction", + "solana-msg", + "solana-pubkey", +] + +[[package]] +name = "solana-program-memory" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1debcdd14cee4dbc2761c1e267e8888188fb469956df0e2144cd6e2962c2532a" +dependencies = [ + "num-traits", + "solana-define-syscall", +] + +[[package]] +name = "solana-program-option" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b49ce216cce72eb0607610d2040b1979d999fe204f73ae2a669c2f4480d3c0" + +[[package]] +name = "solana-program-pack" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ff47a5dd9881187e85a45641405d9d1c57e9ebdc813e2ff74a1aa1f1ec9042" +dependencies = [ + "solana-program-error", +] + +[[package]] +name = "solana-program-runtime" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d4647f4dfed31aaa307d8c4924fec3fc981e88dd340eec45273afa84f3d01a4" +dependencies = [ + "base64 0.22.1", + "bincode", + "enum-iterator", + "itertools 0.12.1", + "libc", + "log", + "num-derive", + "num-traits", + "percentage", + "rand 0.8.5", + "serde", + "solana-compute-budget", + "solana-feature-set", + "solana-log-collector", + "solana-measure", + "solana-metrics", + "solana-sdk", + "solana-timings", + "solana-type-overrides", + "solana-vote", + "solana_rbpf", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-pubkey" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02016ff5f98314c886e219c023bffba188ad8d70dec007247bd7a9da50423ac0" +dependencies = [ + "borsh 0.10.4", + "borsh 1.5.5", + "bs58", + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 4.1.3", + "five8_const", + "getrandom 0.2.15", + "js-sys", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "solana-atomic-u64", + "solana-decode-error", + "solana-define-syscall", + "solana-sanitize", + "solana-sha256-hasher", + "wasm-bindgen", +] + +[[package]] +name = "solana-pubsub-client" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af610bc169985b016e1f66bc9f0cc19559c9da5fb6ee0b8984ea69b1302e6619" +dependencies = [ + "crossbeam-channel", + "futures-util", + "log", + "reqwest", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder", + "solana-rpc-client-api", + "solana-sdk", + "thiserror 1.0.69", + "tokio", + "tokio-stream", + "tokio-tungstenite", + "tungstenite", + "url", +] + +[[package]] +name = "solana-quic-client" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fa9aed25872d9af165499a9a2167d489ceb832d5e6eaa1aafa982286f62e06d" +dependencies = [ + "async-lock", + "async-trait", + "futures", + "itertools 0.12.1", + "lazy_static", + "log", + "quinn", + "quinn-proto", + "rustls 0.23.21", + "solana-connection-cache", + "solana-measure", + "solana-metrics", + "solana-net-utils", + "solana-rpc-client-api", + "solana-sdk", + "solana-streamer", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "solana-rayon-threadlimit" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d0ea6818ea3ae2067b18ba8f82577de19094d7abbb918ffb5cf5d7b0a6ffe88" +dependencies = [ + "lazy_static", + "num_cpus", +] + +[[package]] +name = "solana-rent" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "544fab48aacd3b9c740ef5206f30e8a44ef8bfe5676a9d7b1eed385265ec1265" +dependencies = [ + "serde", + "serde_derive", + "solana-sdk-macro", + "solana-sysvar-id", +] + +[[package]] +name = "solana-rpc-client" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff2d4562f555ed4ca406d88483f2b8ad0248e41ea19721227ffb5c64529bff2" +dependencies = [ + "async-trait", + "base64 0.22.1", + "bincode", + "bs58", + "indicatif", + "log", + "reqwest", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-rpc-client-api", + "solana-sdk", + "solana-transaction-status-client-types", + "solana-version", + "solana-vote-program", + "tokio", +] + +[[package]] +name = "solana-rpc-client-api" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a50f6a180457400c9843980f1dd5db32b1153c295005ca85edb84bb7625acae" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bs58", + "jsonrpc-core", + "reqwest", + "reqwest-middleware", + "semver", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-inline-spl", + "solana-sdk", + "solana-transaction-status-client-types", + "solana-version", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-rpc-client-nonce-utils" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fa3be2840d3b8ebbdab96f62f59e0a9e6f9ba10f27b96a7d80d6897b15ff21a" +dependencies = [ + "solana-rpc-client", + "solana-sdk", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-sanitize" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9677531dd4098d078515c66d69a04bfa0389d364a5c768561c719030b368a9db" + +[[package]] +name = "solana-sdk" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf93cfd5f5af23b59789eba96b6a6afd92a3a18a3fc6652259bfa1f32743caf4" +dependencies = [ + "bincode", + "bitflags 2.8.0", + "borsh 1.5.5", + "bs58", + "bytemuck", + "bytemuck_derive", + "byteorder", + "chrono", + "digest 0.10.7", + "ed25519-dalek", + "ed25519-dalek-bip32", + "getrandom 0.1.16", + "hmac 0.12.1", + "itertools 0.12.1", + "js-sys", + "lazy_static", + "libsecp256k1", + "log", + "memmap2", + "num-derive", + "num-traits", + "num_enum", + "pbkdf2", + "rand 0.7.3", + "rand 0.8.5", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "serde_with", + "sha2 0.10.8", + "sha3", + "siphasher", + "solana-account", + "solana-bn254", + "solana-decode-error", + "solana-derivation-path", + "solana-feature-set", + "solana-inflation", + "solana-instruction", + "solana-native-token", + "solana-packet", + "solana-precompile-error", + "solana-program", + "solana-program-memory", + "solana-pubkey", + "solana-sanitize", + "solana-sdk-macro", + "solana-secp256k1-recover", + "solana-secp256r1-program", + "solana-serde-varint", + "solana-short-vec", + "solana-signature", + "solana-transaction-error", + "thiserror 1.0.69", + "wasm-bindgen", +] + +[[package]] +name = "solana-sdk-macro" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bded40f70accbe97030e5f7163017605e51a2631425229ec2b0a4339bd1163a" +dependencies = [ + "bs58", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "solana-secp256k1-recover" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee25b962814dec3c141e8182474046bae231f0521ed62c9bfdfb6722999ddc18" +dependencies = [ + "borsh 1.5.5", + "libsecp256k1", + "solana-define-syscall", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-secp256r1-program" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec53eff8861ab398b9ca4da7ef8c8da5d4170f8ea26557fc1581638b56326c1" +dependencies = [ + "bytemuck", + "openssl", + "solana-feature-set", + "solana-instruction", + "solana-precompile-error", + "solana-pubkey", +] + +[[package]] +name = "solana-security-txt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183" + +[[package]] +name = "solana-serde-varint" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ff77c37cb995cc53ce1a4b78e5e9961957098677de6fdc6a4783ed37a8b0fcd" +dependencies = [ + "serde", +] + +[[package]] +name = "solana-serialize-utils" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a10eb6e3177828145beaba85d352a4dbc47798fd95c5f86145e1a732684d6d" +dependencies = [ + "solana-instruction", + "solana-pubkey", + "solana-sanitize", +] + +[[package]] +name = "solana-sha256-hasher" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98c4229293979bf8bda7db2243ae75e13695341375577a4c44b07e4f0b7a5d9e" +dependencies = [ + "sha2 0.10.8", + "solana-define-syscall", + "solana-hash", +] + +[[package]] +name = "solana-short-vec" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a2a88d56e6771329970059bcab0fde9a719c8edae173fb26b2c08e427495a" +dependencies = [ + "serde", +] + +[[package]] +name = "solana-signature" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1e8a078879d8430cdfbee8e3c1cdf17da74c19d304662580fc463dc91e17699" +dependencies = [ + "bs58", + "ed25519-dalek", + "generic-array", + "rand 0.8.5", + "serde", + "serde_derive", + "solana-sanitize", +] + +[[package]] +name = "solana-slot-hashes" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88fa2a6e60f2d7016cf95429e0f60cf4a04d4eed167abd1a5f8b08cbda695893" +dependencies = [ + "serde", + "serde_derive", + "solana-hash", + "solana-sysvar-id", +] + +[[package]] +name = "solana-slot-history" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fa66272c308c39a3ce1ca2a9c422de4bdedc28cfe706d6f2c68727bb626eb7" +dependencies = [ + "bv", + "serde", + "serde_derive", + "solana-sysvar-id", +] + +[[package]] +name = "solana-stable-layout" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2243571ebf8c0c9915c7e71b17469e173c6755fa58af8eb529db3dda84e3e19a" +dependencies = [ + "solana-instruction", + "solana-pubkey", +] + +[[package]] +name = "solana-streamer" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fddc2b38975c25199456ff46307c484affb459b84aedefe9618aece2a92326a9" +dependencies = [ + "async-channel", + "bytes", + "crossbeam-channel", + "dashmap", + "futures", + "futures-util", + "governor", + "histogram", + "indexmap 2.7.1", + "itertools 0.12.1", + "libc", + "log", + "nix", + "pem", + "percentage", + "quinn", + "quinn-proto", + "rand 0.8.5", + "rustls 0.23.21", + "smallvec", + "socket2", + "solana-measure", + "solana-metrics", + "solana-perf", + "solana-sdk", + "solana-transaction-metrics-tracker", + "thiserror 1.0.69", + "tokio", + "tokio-util", + "x509-parser", +] + +[[package]] +name = "solana-sysvar-id" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5822b63dd59f124e4920df8d87640a288bb40f4016fd275d028fee0b94a5a51e" +dependencies = [ + "solana-pubkey", +] + +[[package]] +name = "solana-thin-client" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1915dcb44dd5763a30aa32a687057e6a3b16781eb9f5db2800548990560272c3" +dependencies = [ + "bincode", + "log", + "rayon", + "solana-connection-cache", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-sdk", +] + +[[package]] +name = "solana-timings" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "088c4507c8fd4f81c4039d78baf1ea7d68c8b80b2a973ba60838d33d2f7e752d" +dependencies = [ + "eager", + "enum-iterator", + "solana-sdk", +] + +[[package]] +name = "solana-tpu-client" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f944cd29eb540ca7e8df03c4e6043d5b8042eadab29b1848245c847a7c7c555" +dependencies = [ + "async-trait", + "bincode", + "futures-util", + "indexmap 2.7.1", + "indicatif", + "log", + "rayon", + "solana-connection-cache", + "solana-measure", + "solana-pubsub-client", + "solana-rpc-client", + "solana-rpc-client-api", + "solana-sdk", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "solana-transaction-error" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7bd92caae17b4b828864b85cecf6dba6a87ad0ac433606b8bbd58334c74d0251" +dependencies = [ + "serde", + "serde_derive", + "solana-instruction", + "solana-sanitize", +] + +[[package]] +name = "solana-transaction-metrics-tracker" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "551dc5dad276919d24287e14e410759e93b801f2ca47dd9ad6c75eb49af26607" +dependencies = [ + "base64 0.22.1", + "bincode", + "lazy_static", + "log", + "rand 0.8.5", + "solana-perf", + "solana-sdk", + "solana-short-vec", +] + +[[package]] +name = "solana-transaction-status-client-types" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897c0015c246cb9b98cfaee15921c89cd7c1503bd368e9a3fd9336c17cd6be25" +dependencies = [ + "base64 0.22.1", + "bincode", + "bs58", + "serde", + "serde_derive", + "serde_json", + "solana-account-decoder-client-types", + "solana-sdk", + "solana-signature", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-type-overrides" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8e0b8916e7d78678428ca5d669950f6259ac332eab953ed0c8c2c88eebd3d2" +dependencies = [ + "lazy_static", + "rand 0.8.5", +] + +[[package]] +name = "solana-udp-client" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f5c6096b155fb1fb73d03fec2264a9671cbe208f71c4c32521ee9c979d91c75" +dependencies = [ + "async-trait", + "solana-connection-cache", + "solana-net-utils", + "solana-sdk", + "solana-streamer", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "solana-version" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae093290bf86006e323e883b9df845e4bdf84f23c37067cfa9837918ed04c87d" +dependencies = [ + "semver", + "serde", + "serde_derive", + "solana-feature-set", + "solana-sanitize", + "solana-serde-varint", +] + +[[package]] +name = "solana-vote" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8421891f95fe3b8291205e37043396c0fb26c2896cc94d53b153e1ba180992fa" +dependencies = [ + "itertools 0.12.1", + "log", + "serde", + "serde_derive", + "solana-sdk", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-vote-program" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf72a022dbb24dcfe1588aa09679042866eb7c0796ea479500ebe9355a7017f" +dependencies = [ + "bincode", + "log", + "num-derive", + "num-traits", + "serde", + "serde_derive", + "solana-feature-set", + "solana-metrics", + "solana-program", + "solana-program-runtime", + "solana-sdk", + "thiserror 1.0.69", +] + +[[package]] +name = "solana-zk-token-sdk" +version = "2.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b8cc94d7eddf6606c22504889b6528734db56ed3c2f651641453d13c9b233d7" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "byteorder", + "curve25519-dalek 4.1.3", + "itertools 0.12.1", + "lazy_static", + "merlin", + "num-derive", + "num-traits", + "rand 0.8.5", + "serde", + "serde_derive", + "serde_json", + "sha3", + "solana-curve25519", + "solana-derivation-path", + "solana-program", + "solana-sdk", + "subtle", + "thiserror 1.0.69", + "zeroize", +] + +[[package]] +name = "solana_rbpf" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c1941b5ef0c3ce8f2ac5dd984d0fb1a97423c4ff2a02eec81e3913f02e2ac2b" +dependencies = [ + "byteorder", + "combine 3.8.1", + "hash32", + "libc", + "log", + "rand 0.8.5", + "rustc-demangle", + "scroll", + "thiserror 1.0.69", + "winapi", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spl-discriminator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38ea8b6dedb7065887f12d62ed62c1743aa70749e8558f963609793f6fb12bc" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator-derive", +] + +[[package]] +name = "spl-discriminator-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e8418ea6269dcfb01c712f0444d2c75542c04448b480e87de59d2865edc750" +dependencies = [ + "quote", + "spl-discriminator-syn", + "syn 2.0.96", +] + +[[package]] +name = "spl-discriminator-syn" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f05593b7ca9eac7caca309720f2eafb96355e037e6d373b909a80fe7b69b9" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.96", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-memo" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0dba2f2bb6419523405d21c301a32c9f9568354d4742552e7972af801f4bdb3" +dependencies = [ + "solana-program", +] + +[[package]] +name = "spl-pod" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c704c88fc457fa649ba3aabe195c79d885c3f26709efaddc453c8de352c90b87" +dependencies = [ + "borsh 1.5.5", + "bytemuck", + "bytemuck_derive", + "solana-program", + "solana-zk-token-sdk", + "spl-program-error", +] + +[[package]] +name = "spl-program-error" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7b28bed65356558133751cc32b48a7a5ddfc59ac4e941314630bbed1ac10532" +dependencies = [ + "num-derive", + "num-traits", + "solana-program", + "spl-program-error-derive", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-program-error-derive" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d375dd76c517836353e093c2dbb490938ff72821ab568b545fd30ab3256b3e" +dependencies = [ + "proc-macro2", + "quote", + "sha2 0.10.8", + "syn 2.0.96", +] + +[[package]] +name = "spl-tlv-account-resolution" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a75a5f0fcc58126693ed78a17042e9dc53f07e357d6be91789f7d62aff61a4" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", +] + +[[package]] +name = "spl-token" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70a0f06ac7f23dc0984931b1fe309468f14ea58e32660439c1cef19456f5d0e3" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-2022" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c10f3483e48679619c76598d4e4aebb955bc49b0a5cc63323afbf44135c9bf" +dependencies = [ + "arrayref", + "bytemuck", + "num-derive", + "num-traits", + "num_enum", + "solana-program", + "solana-security-txt", + "solana-zk-token-sdk", + "spl-memo", + "spl-pod", + "spl-token", + "spl-token-group-interface", + "spl-token-metadata-interface", + "spl-transfer-hook-interface", + "spl-type-length-value", + "thiserror 1.0.69", +] + +[[package]] +name = "spl-token-group-interface" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8752b85a5ecc1d9f3a43bce3dd9a6a053673aacf5deb513d1cbb88d3534ffd" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", +] + +[[package]] +name = "spl-token-metadata-interface" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6c2318ddff97e006ed9b1291ebec0750a78547f870f62a69c56fe3b46a5d8fc" +dependencies = [ + "borsh 1.5.5", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-type-length-value", +] + +[[package]] +name = "spl-transfer-hook-interface" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a110f33d941275d9f868b96daaa993f1e73b6806cc8836e43075b4d3ad8338a7" +dependencies = [ + "arrayref", + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", + "spl-tlv-account-resolution", + "spl-type-length-value", +] + +[[package]] +name = "spl-type-length-value" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdcd73ec187bc409464c60759232e309f83b52a18a9c5610bf281c9c6432918c" +dependencies = [ + "bytemuck", + "solana-program", + "spl-discriminator", + "spl-pod", + "spl-program-error", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "synstructure" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unicode-xid", +] + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "task-local-extensions" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba323866e5d033818e3240feeb9f7db2c4296674e4d9e16b97b7bf8f490434e8" +dependencies = [ + "pin-utils", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc" +dependencies = [ + "thiserror-impl 2.0.11", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "time" +version = "0.3.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinystr" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls 0.21.12", + "tokio", + "tokio-rustls", + "tungstenite", + "webpki-roots 0.25.4", +] + +[[package]] +name = "tokio-util" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap 2.7.1", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "tracing-core" +version = "0.1.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.8.5", + "rustls 0.21.12", + "sha1", + "thiserror 1.0.69", + "url", + "utf-8", + "webpki-roots 0.24.0", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +dependencies = [ + "void", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "uriparse" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" +dependencies = [ + "fnv", + "lazy_static", +] + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.96", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "0.26.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd5da49bdf1f30054cfe0b8ce2958b8fbeb67c4d82c8967a598af481bef255c" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webpki-roots" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b291546d5d9d1eab74f069c77749f2cb8504a12caa20f0f2de93ddbf6f411888" +dependencies = [ + "rustls-webpki 0.101.7", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs", + "base64 0.13.1", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror 1.0.69", + "time", +] + +[[package]] +name = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "synstructure 0.13.1", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "synstructure 0.13.1", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "zstd" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.13+zstd.1.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/dephy-vending_machine-examples/balance-payment-sdk/Cargo.toml b/dephy-vending_machine-examples/balance-payment-sdk/Cargo.toml new file mode 100644 index 0000000..aff6e3c --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "dephy-balance-payment-sdk" +version = "0.1.0" +edition = "2021" +license.workspace = true + +[features] +default = ["serde"] +serde = ["dep:serde", "dep:serde_with"] + +[dependencies] +arrayref = { workspace = true } +borsh = { workspace = true } +curve25519-dalek = { workspace = true } +num-derive = { workspace = true } +num-traits = { workspace = true } +serde = { workspace = true, optional = true } +serde_json = { workspace = true } +serde_with = { workspace = true, optional = true } +sha2 = { workspace = true } +solana-client = { workspace = true } +solana-program = { workspace = true } +solana-sdk = { workspace = true } +solana-zk-token-sdk = { workspace = true } +thiserror = { workspace = true } +tracing = { workspace = true } diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/error.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/error.rs new file mode 100644 index 0000000..78b612d --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/error.rs @@ -0,0 +1,16 @@ +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("Io error: {0}")] + Io(#[from] std::io::Error), + #[error("Parse pubkey error: ")] + ParsePubkey(#[from] solana_program::pubkey::ParsePubkeyError), + #[error("Serde json error: {0}")] + SerdeJson(#[from] serde_json::Error), + #[error("Solana client error: {0}")] + SolanaClient(#[from] solana_client::client_error::ClientError), + #[error("Signature verification failed: {0}")] + SignatureVerificationFailed(String), + #[error("Keypair read failed: {0}")] + KeypairReadFailed(Box), +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/global_account.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/global_account.rs new file mode 100644 index 0000000..ad25c9a --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/global_account.rs @@ -0,0 +1,77 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_program::pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct GlobalAccount { + pub discriminator: [u8; 8], + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub authority: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub bot: Pubkey, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub treasury: Pubkey, +} + +impl GlobalAccount { + pub const LEN: usize = 104; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_program::account_info::AccountInfo<'a>> for GlobalAccount { + type Error = std::io::Error; + + fn try_from( + account_info: &solana_program::account_info::AccountInfo<'a>, + ) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for GlobalAccount { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for GlobalAccount {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for GlobalAccount { + fn owner() -> Pubkey { + crate::BALANCE_PAYMENT_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for GlobalAccount {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for GlobalAccount { + const DISCRIMINATOR: [u8; 8] = [0; 8]; +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/lock_account.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/lock_account.rs new file mode 100644 index 0000000..07ca4c5 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/lock_account.rs @@ -0,0 +1,62 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct LockAccount { + pub discriminator: [u8; 8], + pub amount: u64, +} + +impl LockAccount { + pub const LEN: usize = 16; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_program::account_info::AccountInfo<'a>> for LockAccount { + type Error = std::io::Error; + + fn try_from( + account_info: &solana_program::account_info::AccountInfo<'a>, + ) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for LockAccount { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for LockAccount {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for LockAccount { + fn owner() -> Pubkey { + crate::BALANCE_PAYMENT_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for LockAccount {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for LockAccount { + const DISCRIMINATOR: [u8; 8] = [0; 8]; +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/mod.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/mod.rs new file mode 100644 index 0000000..c609503 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/mod.rs @@ -0,0 +1,14 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#global_account; +pub(crate) mod r#lock_account; +pub(crate) mod r#user_account; + +pub use self::r#global_account::*; +pub use self::r#lock_account::*; +pub use self::r#user_account::*; diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/user_account.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/user_account.rs new file mode 100644 index 0000000..aee821a --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/accounts/user_account.rs @@ -0,0 +1,69 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; +use solana_program::pubkey::Pubkey; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct UserAccount { + pub discriminator: [u8; 8], + pub nonce: u64, + pub locked_amount: u64, + #[cfg_attr( + feature = "serde", + serde(with = "serde_with::As::") + )] + pub vault: Pubkey, +} + +impl UserAccount { + pub const LEN: usize = 56; + + #[inline(always)] + pub fn from_bytes(data: &[u8]) -> Result { + let mut data = data; + Self::deserialize(&mut data) + } +} + +impl<'a> TryFrom<&solana_program::account_info::AccountInfo<'a>> for UserAccount { + type Error = std::io::Error; + + fn try_from( + account_info: &solana_program::account_info::AccountInfo<'a>, + ) -> Result { + let mut data: &[u8] = &(*account_info.data).borrow(); + Self::deserialize(&mut data) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountDeserialize for UserAccount { + fn try_deserialize_unchecked(buf: &mut &[u8]) -> anchor_lang::Result { + Ok(Self::deserialize(buf)?) + } +} + +#[cfg(feature = "anchor")] +impl anchor_lang::AccountSerialize for UserAccount {} + +#[cfg(feature = "anchor")] +impl anchor_lang::Owner for UserAccount { + fn owner() -> Pubkey { + crate::BALANCE_PAYMENT_ID + } +} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::IdlBuild for UserAccount {} + +#[cfg(feature = "anchor-idl-build")] +impl anchor_lang::Discriminator for UserAccount { + const DISCRIMINATOR: [u8; 8] = [0; 8]; +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/errors/balance_payment.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/errors/balance_payment.rs new file mode 100644 index 0000000..49eaf84 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/errors/balance_payment.rs @@ -0,0 +1,43 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use num_derive::FromPrimitive; +use thiserror::Error; + +#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)] +pub enum BalancePaymentError { + /// 6000 - Unauthorized access. + #[error("Unauthorized access.")] + Unauthorized = 0x1770, + /// 6001 - Insufficient funds. + #[error("Insufficient funds.")] + InsufficientFunds = 0x1771, + /// 6002 - The signature format or recovery ID is incorrect. + #[error("The signature format or recovery ID is incorrect.")] + SignatureFormatInvalid = 0x1772, + /// 6003 - Failed to recover public key from signature. + #[error("Failed to recover public key from signature.")] + SignatureRecoveryFailed = 0x1773, + /// 6004 - The recovered public key does not match the user's public key. + #[error("The recovered public key does not match the user's public key.")] + SignatureMismatch = 0x1774, + /// 6005 - The signature is expired. + #[error("The signature is expired.")] + SignatureExpired = 0x1775, +} + +impl solana_program::program_error::PrintProgramError for BalancePaymentError { + fn print(&self) { + solana_program::msg!(&self.to_string()); + } +} + +impl solana_program::decode_error::DecodeError for BalancePaymentError { + fn type_of() -> &'static str { + "BalancePaymentError" + } +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/errors/mod.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/errors/mod.rs new file mode 100644 index 0000000..4fe38d1 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/errors/mod.rs @@ -0,0 +1,10 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod balance_payment; + +pub use self::balance_payment::BalancePaymentError; diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/deposit.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/deposit.rs new file mode 100644 index 0000000..3375c27 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/deposit.rs @@ -0,0 +1,472 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct Deposit { + pub user_account: solana_program::pubkey::Pubkey, + + pub user: solana_program::pubkey::Pubkey, + + pub vault: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl Deposit { + pub fn instruction( + &self, + args: DepositInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: DepositInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.vault, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = DepositInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct DepositInstructionData { + discriminator: [u8; 8], +} + +impl DepositInstructionData { + pub fn new() -> Self { + Self { + discriminator: [242, 35, 198, 137, 82, 225, 242, 182], + } + } +} + +impl Default for DepositInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct DepositInstructionArgs { + pub amount: u64, +} + +/// Instruction builder for `Deposit`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` user_account +/// 1. `[writable, signer]` user +/// 2. `[writable]` vault +/// 3. `[writable, signer]` payer +/// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct DepositBuilder { + user_account: Option, + user: Option, + vault: Option, + payer: Option, + system_program: Option, + amount: Option, + __remaining_accounts: Vec, +} + +impl DepositBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn user_account(&mut self, user_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: solana_program::pubkey::Pubkey) -> &mut Self { + self.user = Some(user); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: solana_program::pubkey::Pubkey) -> &mut Self { + self.vault = Some(vault); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = Deposit { + user_account: self.user_account.expect("user_account is not set"), + user: self.user.expect("user is not set"), + vault: self.vault.expect("vault is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = DepositInstructionArgs { + amount: self.amount.clone().expect("amount is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `deposit` CPI accounts. +pub struct DepositCpiAccounts<'a, 'b> { + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `deposit` CPI instruction. +pub struct DepositCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: DepositInstructionArgs, +} + +impl<'a, 'b> DepositCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: DepositCpiAccounts<'a, 'b>, + args: DepositInstructionArgs, + ) -> Self { + Self { + __program: program, + user_account: accounts.user_account, + user: accounts.user, + vault: accounts.vault, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.vault.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = DepositInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.user_account.clone()); + account_infos.push(self.user.clone()); + account_infos.push(self.vault.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Deposit` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` user_account +/// 1. `[writable, signer]` user +/// 2. `[writable]` vault +/// 3. `[writable, signer]` payer +/// 4. `[]` system_program +#[derive(Clone, Debug)] +pub struct DepositCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> DepositCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(DepositCpiBuilderInstruction { + __program: program, + user_account: None, + user: None, + vault: None, + payer: None, + system_program: None, + amount: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn user_account( + &mut self, + user_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.user = Some(user); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.vault = Some(vault); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.instruction.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = DepositInstructionArgs { + amount: self.instruction.amount.clone().expect("amount is not set"), + }; + let instruction = DepositCpi { + __program: self.instruction.__program, + + user_account: self + .instruction + .user_account + .expect("user_account is not set"), + + user: self.instruction.user.expect("user is not set"), + + vault: self.instruction.vault.expect("vault is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct DepositCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + user_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + user: Option<&'b solana_program::account_info::AccountInfo<'a>>, + vault: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + amount: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/initialize.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/initialize.rs new file mode 100644 index 0000000..3e307bf --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/initialize.rs @@ -0,0 +1,475 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct Initialize { + pub global_account: solana_program::pubkey::Pubkey, + + pub authority: solana_program::pubkey::Pubkey, + + pub treasury: solana_program::pubkey::Pubkey, + + pub bot: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl Initialize { + pub fn instruction(&self) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(6 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.global_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.authority, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.treasury, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.bot, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = InitializeInstructionData::new().try_to_vec().unwrap(); + + solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct InitializeInstructionData { + discriminator: [u8; 8], +} + +impl InitializeInstructionData { + pub fn new() -> Self { + Self { + discriminator: [175, 175, 109, 31, 13, 152, 155, 237], + } + } +} + +impl Default for InitializeInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `Initialize`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` global_account +/// 1. `[]` authority +/// 2. `[]` treasury +/// 3. `[]` bot +/// 4. `[writable, signer]` payer +/// 5. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct InitializeBuilder { + global_account: Option, + authority: Option, + treasury: Option, + bot: Option, + payer: Option, + system_program: Option, + __remaining_accounts: Vec, +} + +impl InitializeBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn global_account(&mut self, global_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_program::pubkey::Pubkey) -> &mut Self { + self.authority = Some(authority); + self + } + #[inline(always)] + pub fn treasury(&mut self, treasury: solana_program::pubkey::Pubkey) -> &mut Self { + self.treasury = Some(treasury); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: solana_program::pubkey::Pubkey) -> &mut Self { + self.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = Initialize { + global_account: self.global_account.expect("global_account is not set"), + authority: self.authority.expect("authority is not set"), + treasury: self.treasury.expect("treasury is not set"), + bot: self.bot.expect("bot is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `initialize` CPI accounts. +pub struct InitializeCpiAccounts<'a, 'b> { + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + + pub treasury: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `initialize` CPI instruction. +pub struct InitializeCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + + pub treasury: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +impl<'a, 'b> InitializeCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: InitializeCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + global_account: accounts.global_account, + authority: accounts.authority, + treasury: accounts.treasury, + bot: accounts.bot, + payer: accounts.payer, + system_program: accounts.system_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(6 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.global_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.authority.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.treasury.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.bot.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = InitializeInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(7 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.global_account.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.treasury.clone()); + account_infos.push(self.bot.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Initialize` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` global_account +/// 1. `[]` authority +/// 2. `[]` treasury +/// 3. `[]` bot +/// 4. `[writable, signer]` payer +/// 5. `[]` system_program +#[derive(Clone, Debug)] +pub struct InitializeCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> InitializeCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(InitializeCpiBuilderInstruction { + __program: program, + global_account: None, + authority: None, + treasury: None, + bot: None, + payer: None, + system_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn global_account( + &mut self, + global_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn authority( + &mut self, + authority: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + #[inline(always)] + pub fn treasury( + &mut self, + treasury: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.treasury = Some(treasury); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let instruction = InitializeCpi { + __program: self.instruction.__program, + + global_account: self + .instruction + .global_account + .expect("global_account is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + treasury: self.instruction.treasury.expect("treasury is not set"), + + bot: self.instruction.bot.expect("bot is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct InitializeCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + global_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + treasury: Option<&'b solana_program::account_info::AccountInfo<'a>>, + bot: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/lock.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/lock.rs new file mode 100644 index 0000000..14c1b79 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/lock.rs @@ -0,0 +1,606 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::ED25519RecoverInfo; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct Lock { + pub global_account: solana_program::pubkey::Pubkey, + + pub user_account: solana_program::pubkey::Pubkey, + + pub user: solana_program::pubkey::Pubkey, + + pub lock_account: solana_program::pubkey::Pubkey, + + pub vault: solana_program::pubkey::Pubkey, + + pub bot: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl Lock { + pub fn instruction( + &self, + args: LockInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: LockInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.global_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.lock_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.vault, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.bot, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = LockInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct LockInstructionData { + discriminator: [u8; 8], +} + +impl LockInstructionData { + pub fn new() -> Self { + Self { + discriminator: [21, 19, 208, 43, 237, 62, 255, 87], + } + } +} + +impl Default for LockInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct LockInstructionArgs { + pub recover_info: ED25519RecoverInfo, + pub amount: u64, +} + +/// Instruction builder for `Lock`. +/// +/// ### Accounts: +/// +/// 0. `[]` global_account +/// 1. `[writable]` user_account +/// 2. `[writable]` user +/// 3. `[writable]` lock_account +/// 4. `[]` vault +/// 5. `[signer]` bot +/// 6. `[writable, signer]` payer +/// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct LockBuilder { + global_account: Option, + user_account: Option, + user: Option, + lock_account: Option, + vault: Option, + bot: Option, + payer: Option, + system_program: Option, + recover_info: Option, + amount: Option, + __remaining_accounts: Vec, +} + +impl LockBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn global_account(&mut self, global_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn user_account(&mut self, user_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: solana_program::pubkey::Pubkey) -> &mut Self { + self.user = Some(user); + self + } + #[inline(always)] + pub fn lock_account(&mut self, lock_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.lock_account = Some(lock_account); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: solana_program::pubkey::Pubkey) -> &mut Self { + self.vault = Some(vault); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: solana_program::pubkey::Pubkey) -> &mut Self { + self.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn recover_info(&mut self, recover_info: ED25519RecoverInfo) -> &mut Self { + self.recover_info = Some(recover_info); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = Lock { + global_account: self.global_account.expect("global_account is not set"), + user_account: self.user_account.expect("user_account is not set"), + user: self.user.expect("user is not set"), + lock_account: self.lock_account.expect("lock_account is not set"), + vault: self.vault.expect("vault is not set"), + bot: self.bot.expect("bot is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = LockInstructionArgs { + recover_info: self.recover_info.clone().expect("recover_info is not set"), + amount: self.amount.clone().expect("amount is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `lock` CPI accounts. +pub struct LockCpiAccounts<'a, 'b> { + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub lock_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `lock` CPI instruction. +pub struct LockCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub lock_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: LockInstructionArgs, +} + +impl<'a, 'b> LockCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: LockCpiAccounts<'a, 'b>, + args: LockInstructionArgs, + ) -> Self { + Self { + __program: program, + global_account: accounts.global_account, + user_account: accounts.user_account, + user: accounts.user, + lock_account: accounts.lock_account, + vault: accounts.vault, + bot: accounts.bot, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.global_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.lock_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.vault.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.bot.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = LockInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(9 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.global_account.clone()); + account_infos.push(self.user_account.clone()); + account_infos.push(self.user.clone()); + account_infos.push(self.lock_account.clone()); + account_infos.push(self.vault.clone()); + account_infos.push(self.bot.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Lock` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` global_account +/// 1. `[writable]` user_account +/// 2. `[writable]` user +/// 3. `[writable]` lock_account +/// 4. `[]` vault +/// 5. `[signer]` bot +/// 6. `[writable, signer]` payer +/// 7. `[]` system_program +#[derive(Clone, Debug)] +pub struct LockCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> LockCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(LockCpiBuilderInstruction { + __program: program, + global_account: None, + user_account: None, + user: None, + lock_account: None, + vault: None, + bot: None, + payer: None, + system_program: None, + recover_info: None, + amount: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn global_account( + &mut self, + global_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn user_account( + &mut self, + user_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.user = Some(user); + self + } + #[inline(always)] + pub fn lock_account( + &mut self, + lock_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.lock_account = Some(lock_account); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.vault = Some(vault); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn recover_info(&mut self, recover_info: ED25519RecoverInfo) -> &mut Self { + self.instruction.recover_info = Some(recover_info); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.instruction.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = LockInstructionArgs { + recover_info: self + .instruction + .recover_info + .clone() + .expect("recover_info is not set"), + amount: self.instruction.amount.clone().expect("amount is not set"), + }; + let instruction = LockCpi { + __program: self.instruction.__program, + + global_account: self + .instruction + .global_account + .expect("global_account is not set"), + + user_account: self + .instruction + .user_account + .expect("user_account is not set"), + + user: self.instruction.user.expect("user is not set"), + + lock_account: self + .instruction + .lock_account + .expect("lock_account is not set"), + + vault: self.instruction.vault.expect("vault is not set"), + + bot: self.instruction.bot.expect("bot is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct LockCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + global_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + user_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + user: Option<&'b solana_program::account_info::AccountInfo<'a>>, + lock_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + vault: Option<&'b solana_program::account_info::AccountInfo<'a>>, + bot: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + recover_info: Option, + amount: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/mod.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/mod.rs new file mode 100644 index 0000000..e9e2ab0 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/mod.rs @@ -0,0 +1,26 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#deposit; +pub(crate) mod r#initialize; +pub(crate) mod r#lock; +pub(crate) mod r#pay; +pub(crate) mod r#register; +pub(crate) mod r#set_bot; +pub(crate) mod r#set_treasury; +pub(crate) mod r#settle; +pub(crate) mod r#withdraw; + +pub use self::r#deposit::*; +pub use self::r#initialize::*; +pub use self::r#lock::*; +pub use self::r#pay::*; +pub use self::r#register::*; +pub use self::r#set_bot::*; +pub use self::r#set_treasury::*; +pub use self::r#settle::*; +pub use self::r#withdraw::*; diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/pay.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/pay.rs new file mode 100644 index 0000000..afe1322 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/pay.rs @@ -0,0 +1,610 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use crate::generated::types::ED25519RecoverInfo; +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct Pay { + pub global_account: solana_program::pubkey::Pubkey, + + pub user_account: solana_program::pubkey::Pubkey, + + pub user: solana_program::pubkey::Pubkey, + + pub treasury: solana_program::pubkey::Pubkey, + + pub vault: solana_program::pubkey::Pubkey, + + pub bot: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl Pay { + pub fn instruction( + &self, + args: PayInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: PayInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.global_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.treasury, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.vault, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.bot, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = PayInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct PayInstructionData { + discriminator: [u8; 8], +} + +impl PayInstructionData { + pub fn new() -> Self { + Self { + discriminator: [119, 18, 216, 65, 192, 117, 122, 220], + } + } +} + +impl Default for PayInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct PayInstructionArgs { + pub recover_info: ED25519RecoverInfo, + pub amount_to_transfer: u64, +} + +/// Instruction builder for `Pay`. +/// +/// ### Accounts: +/// +/// 0. `[]` global_account +/// 1. `[writable]` user_account +/// 2. `[writable]` user +/// 3. `[writable]` treasury +/// 4. `[writable]` vault +/// 5. `[signer]` bot +/// 6. `[writable, signer]` payer +/// 7. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct PayBuilder { + global_account: Option, + user_account: Option, + user: Option, + treasury: Option, + vault: Option, + bot: Option, + payer: Option, + system_program: Option, + recover_info: Option, + amount_to_transfer: Option, + __remaining_accounts: Vec, +} + +impl PayBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn global_account(&mut self, global_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn user_account(&mut self, user_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: solana_program::pubkey::Pubkey) -> &mut Self { + self.user = Some(user); + self + } + #[inline(always)] + pub fn treasury(&mut self, treasury: solana_program::pubkey::Pubkey) -> &mut Self { + self.treasury = Some(treasury); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: solana_program::pubkey::Pubkey) -> &mut Self { + self.vault = Some(vault); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: solana_program::pubkey::Pubkey) -> &mut Self { + self.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn recover_info(&mut self, recover_info: ED25519RecoverInfo) -> &mut Self { + self.recover_info = Some(recover_info); + self + } + #[inline(always)] + pub fn amount_to_transfer(&mut self, amount_to_transfer: u64) -> &mut Self { + self.amount_to_transfer = Some(amount_to_transfer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = Pay { + global_account: self.global_account.expect("global_account is not set"), + user_account: self.user_account.expect("user_account is not set"), + user: self.user.expect("user is not set"), + treasury: self.treasury.expect("treasury is not set"), + vault: self.vault.expect("vault is not set"), + bot: self.bot.expect("bot is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = PayInstructionArgs { + recover_info: self.recover_info.clone().expect("recover_info is not set"), + amount_to_transfer: self + .amount_to_transfer + .clone() + .expect("amount_to_transfer is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `pay` CPI accounts. +pub struct PayCpiAccounts<'a, 'b> { + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub treasury: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `pay` CPI instruction. +pub struct PayCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub treasury: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: PayInstructionArgs, +} + +impl<'a, 'b> PayCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: PayCpiAccounts<'a, 'b>, + args: PayInstructionArgs, + ) -> Self { + Self { + __program: program, + global_account: accounts.global_account, + user_account: accounts.user_account, + user: accounts.user, + treasury: accounts.treasury, + vault: accounts.vault, + bot: accounts.bot, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(8 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.global_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.treasury.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.vault.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.bot.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = PayInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(9 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.global_account.clone()); + account_infos.push(self.user_account.clone()); + account_infos.push(self.user.clone()); + account_infos.push(self.treasury.clone()); + account_infos.push(self.vault.clone()); + account_infos.push(self.bot.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Pay` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` global_account +/// 1. `[writable]` user_account +/// 2. `[writable]` user +/// 3. `[writable]` treasury +/// 4. `[writable]` vault +/// 5. `[signer]` bot +/// 6. `[writable, signer]` payer +/// 7. `[]` system_program +#[derive(Clone, Debug)] +pub struct PayCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> PayCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(PayCpiBuilderInstruction { + __program: program, + global_account: None, + user_account: None, + user: None, + treasury: None, + vault: None, + bot: None, + payer: None, + system_program: None, + recover_info: None, + amount_to_transfer: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn global_account( + &mut self, + global_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn user_account( + &mut self, + user_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.user = Some(user); + self + } + #[inline(always)] + pub fn treasury( + &mut self, + treasury: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.treasury = Some(treasury); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.vault = Some(vault); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn recover_info(&mut self, recover_info: ED25519RecoverInfo) -> &mut Self { + self.instruction.recover_info = Some(recover_info); + self + } + #[inline(always)] + pub fn amount_to_transfer(&mut self, amount_to_transfer: u64) -> &mut Self { + self.instruction.amount_to_transfer = Some(amount_to_transfer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = PayInstructionArgs { + recover_info: self + .instruction + .recover_info + .clone() + .expect("recover_info is not set"), + amount_to_transfer: self + .instruction + .amount_to_transfer + .clone() + .expect("amount_to_transfer is not set"), + }; + let instruction = PayCpi { + __program: self.instruction.__program, + + global_account: self + .instruction + .global_account + .expect("global_account is not set"), + + user_account: self + .instruction + .user_account + .expect("user_account is not set"), + + user: self.instruction.user.expect("user is not set"), + + treasury: self.instruction.treasury.expect("treasury is not set"), + + vault: self.instruction.vault.expect("vault is not set"), + + bot: self.instruction.bot.expect("bot is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct PayCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + global_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + user_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + user: Option<&'b solana_program::account_info::AccountInfo<'a>>, + treasury: Option<&'b solana_program::account_info::AccountInfo<'a>>, + vault: Option<&'b solana_program::account_info::AccountInfo<'a>>, + bot: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + recover_info: Option, + amount_to_transfer: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/register.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/register.rs new file mode 100644 index 0000000..f9160de --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/register.rs @@ -0,0 +1,434 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct Register { + pub user_account: solana_program::pubkey::Pubkey, + + pub user: solana_program::pubkey::Pubkey, + + pub vault: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl Register { + pub fn instruction(&self) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.user, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.vault, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let data = RegisterInstructionData::new().try_to_vec().unwrap(); + + solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct RegisterInstructionData { + discriminator: [u8; 8], +} + +impl RegisterInstructionData { + pub fn new() -> Self { + Self { + discriminator: [211, 124, 67, 15, 211, 194, 178, 240], + } + } +} + +impl Default for RegisterInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `Register`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` user_account +/// 1. `[signer]` user +/// 2. `[]` vault +/// 3. `[writable, signer]` payer +/// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct RegisterBuilder { + user_account: Option, + user: Option, + vault: Option, + payer: Option, + system_program: Option, + __remaining_accounts: Vec, +} + +impl RegisterBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn user_account(&mut self, user_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: solana_program::pubkey::Pubkey) -> &mut Self { + self.user = Some(user); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: solana_program::pubkey::Pubkey) -> &mut Self { + self.vault = Some(vault); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = Register { + user_account: self.user_account.expect("user_account is not set"), + user: self.user.expect("user is not set"), + vault: self.vault.expect("vault is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `register` CPI accounts. +pub struct RegisterCpiAccounts<'a, 'b> { + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `register` CPI instruction. +pub struct RegisterCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +impl<'a, 'b> RegisterCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: RegisterCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + user_account: accounts.user_account, + user: accounts.user, + vault: accounts.vault, + payer: accounts.payer, + system_program: accounts.system_program, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.user.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.vault.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = RegisterInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.user_account.clone()); + account_infos.push(self.user.clone()); + account_infos.push(self.vault.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Register` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` user_account +/// 1. `[signer]` user +/// 2. `[]` vault +/// 3. `[writable, signer]` payer +/// 4. `[]` system_program +#[derive(Clone, Debug)] +pub struct RegisterCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> RegisterCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(RegisterCpiBuilderInstruction { + __program: program, + user_account: None, + user: None, + vault: None, + payer: None, + system_program: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn user_account( + &mut self, + user_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.user = Some(user); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.vault = Some(vault); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let instruction = RegisterCpi { + __program: self.instruction.__program, + + user_account: self + .instruction + .user_account + .expect("user_account is not set"), + + user: self.instruction.user.expect("user is not set"), + + vault: self.instruction.vault.expect("vault is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct RegisterCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + user_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + user: Option<&'b solana_program::account_info::AccountInfo<'a>>, + vault: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/set_bot.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/set_bot.rs new file mode 100644 index 0000000..4950961 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/set_bot.rs @@ -0,0 +1,395 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct SetBot { + pub global_account: solana_program::pubkey::Pubkey, + + pub authority: solana_program::pubkey::Pubkey, + + pub bot: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, +} + +impl SetBot { + pub fn instruction(&self) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.global_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.authority, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.bot, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.extend_from_slice(remaining_accounts); + let data = SetBotInstructionData::new().try_to_vec().unwrap(); + + solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetBotInstructionData { + discriminator: [u8; 8], +} + +impl SetBotInstructionData { + pub fn new() -> Self { + Self { + discriminator: [136, 185, 99, 236, 200, 131, 204, 118], + } + } +} + +impl Default for SetBotInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `SetBot`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` global_account +/// 1. `[signer]` authority +/// 2. `[]` bot +/// 3. `[writable, signer]` payer +#[derive(Clone, Debug, Default)] +pub struct SetBotBuilder { + global_account: Option, + authority: Option, + bot: Option, + payer: Option, + __remaining_accounts: Vec, +} + +impl SetBotBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn global_account(&mut self, global_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_program::pubkey::Pubkey) -> &mut Self { + self.authority = Some(authority); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: solana_program::pubkey::Pubkey) -> &mut Self { + self.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = SetBot { + global_account: self.global_account.expect("global_account is not set"), + authority: self.authority.expect("authority is not set"), + bot: self.bot.expect("bot is not set"), + payer: self.payer.expect("payer is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `set_bot` CPI accounts. +pub struct SetBotCpiAccounts<'a, 'b> { + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `set_bot` CPI instruction. +pub struct SetBotCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, +} + +impl<'a, 'b> SetBotCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: SetBotCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + global_account: accounts.global_account, + authority: accounts.authority, + bot: accounts.bot, + payer: accounts.payer, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.global_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.authority.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.bot.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = SetBotInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(5 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.global_account.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.bot.clone()); + account_infos.push(self.payer.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SetBot` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` global_account +/// 1. `[signer]` authority +/// 2. `[]` bot +/// 3. `[writable, signer]` payer +#[derive(Clone, Debug)] +pub struct SetBotCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SetBotCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SetBotCpiBuilderInstruction { + __program: program, + global_account: None, + authority: None, + bot: None, + payer: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn global_account( + &mut self, + global_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn authority( + &mut self, + authority: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let instruction = SetBotCpi { + __program: self.instruction.__program, + + global_account: self + .instruction + .global_account + .expect("global_account is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + bot: self.instruction.bot.expect("bot is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SetBotCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + global_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + bot: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/set_treasury.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/set_treasury.rs new file mode 100644 index 0000000..edc79a7 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/set_treasury.rs @@ -0,0 +1,399 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct SetTreasury { + pub global_account: solana_program::pubkey::Pubkey, + + pub authority: solana_program::pubkey::Pubkey, + + pub treasury: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, +} + +impl SetTreasury { + pub fn instruction(&self) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(&[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.global_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.authority, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.treasury, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.extend_from_slice(remaining_accounts); + let data = SetTreasuryInstructionData::new().try_to_vec().unwrap(); + + solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SetTreasuryInstructionData { + discriminator: [u8; 8], +} + +impl SetTreasuryInstructionData { + pub fn new() -> Self { + Self { + discriminator: [57, 97, 196, 95, 195, 206, 106, 136], + } + } +} + +impl Default for SetTreasuryInstructionData { + fn default() -> Self { + Self::new() + } +} + +/// Instruction builder for `SetTreasury`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` global_account +/// 1. `[signer]` authority +/// 2. `[]` treasury +/// 3. `[writable, signer]` payer +#[derive(Clone, Debug, Default)] +pub struct SetTreasuryBuilder { + global_account: Option, + authority: Option, + treasury: Option, + payer: Option, + __remaining_accounts: Vec, +} + +impl SetTreasuryBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn global_account(&mut self, global_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn authority(&mut self, authority: solana_program::pubkey::Pubkey) -> &mut Self { + self.authority = Some(authority); + self + } + #[inline(always)] + pub fn treasury(&mut self, treasury: solana_program::pubkey::Pubkey) -> &mut Self { + self.treasury = Some(treasury); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = SetTreasury { + global_account: self.global_account.expect("global_account is not set"), + authority: self.authority.expect("authority is not set"), + treasury: self.treasury.expect("treasury is not set"), + payer: self.payer.expect("payer is not set"), + }; + + accounts.instruction_with_remaining_accounts(&self.__remaining_accounts) + } +} + +/// `set_treasury` CPI accounts. +pub struct SetTreasuryCpiAccounts<'a, 'b> { + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + + pub treasury: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `set_treasury` CPI instruction. +pub struct SetTreasuryCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub authority: &'b solana_program::account_info::AccountInfo<'a>, + + pub treasury: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, +} + +impl<'a, 'b> SetTreasuryCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: SetTreasuryCpiAccounts<'a, 'b>, + ) -> Self { + Self { + __program: program, + global_account: accounts.global_account, + authority: accounts.authority, + treasury: accounts.treasury, + payer: accounts.payer, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(4 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.global_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.authority.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.treasury.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let data = SetTreasuryInstructionData::new().try_to_vec().unwrap(); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(5 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.global_account.clone()); + account_infos.push(self.authority.clone()); + account_infos.push(self.treasury.clone()); + account_infos.push(self.payer.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `SetTreasury` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` global_account +/// 1. `[signer]` authority +/// 2. `[]` treasury +/// 3. `[writable, signer]` payer +#[derive(Clone, Debug)] +pub struct SetTreasuryCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SetTreasuryCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SetTreasuryCpiBuilderInstruction { + __program: program, + global_account: None, + authority: None, + treasury: None, + payer: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn global_account( + &mut self, + global_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn authority( + &mut self, + authority: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.authority = Some(authority); + self + } + #[inline(always)] + pub fn treasury( + &mut self, + treasury: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.treasury = Some(treasury); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let instruction = SetTreasuryCpi { + __program: self.instruction.__program, + + global_account: self + .instruction + .global_account + .expect("global_account is not set"), + + authority: self.instruction.authority.expect("authority is not set"), + + treasury: self.instruction.treasury.expect("treasury is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SetTreasuryCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + global_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + authority: Option<&'b solana_program::account_info::AccountInfo<'a>>, + treasury: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/settle.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/settle.rs new file mode 100644 index 0000000..7839d3b --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/settle.rs @@ -0,0 +1,645 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct Settle { + pub global_account: solana_program::pubkey::Pubkey, + + pub user_account: solana_program::pubkey::Pubkey, + + pub user: solana_program::pubkey::Pubkey, + + pub treasury: solana_program::pubkey::Pubkey, + + pub lock_account: solana_program::pubkey::Pubkey, + + pub vault: solana_program::pubkey::Pubkey, + + pub bot: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl Settle { + pub fn instruction( + &self, + args: SettleInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: SettleInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(9 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.global_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.treasury, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.lock_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.vault, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.bot, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = SettleInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SettleInstructionData { + discriminator: [u8; 8], +} + +impl SettleInstructionData { + pub fn new() -> Self { + Self { + discriminator: [175, 42, 185, 87, 144, 131, 102, 212], + } + } +} + +impl Default for SettleInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct SettleInstructionArgs { + pub nonce: u64, + pub amount_to_transfer: u64, +} + +/// Instruction builder for `Settle`. +/// +/// ### Accounts: +/// +/// 0. `[]` global_account +/// 1. `[writable]` user_account +/// 2. `[writable]` user +/// 3. `[writable]` treasury +/// 4. `[writable]` lock_account +/// 5. `[writable]` vault +/// 6. `[signer]` bot +/// 7. `[writable, signer]` payer +/// 8. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct SettleBuilder { + global_account: Option, + user_account: Option, + user: Option, + treasury: Option, + lock_account: Option, + vault: Option, + bot: Option, + payer: Option, + system_program: Option, + nonce: Option, + amount_to_transfer: Option, + __remaining_accounts: Vec, +} + +impl SettleBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn global_account(&mut self, global_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn user_account(&mut self, user_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: solana_program::pubkey::Pubkey) -> &mut Self { + self.user = Some(user); + self + } + #[inline(always)] + pub fn treasury(&mut self, treasury: solana_program::pubkey::Pubkey) -> &mut Self { + self.treasury = Some(treasury); + self + } + #[inline(always)] + pub fn lock_account(&mut self, lock_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.lock_account = Some(lock_account); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: solana_program::pubkey::Pubkey) -> &mut Self { + self.vault = Some(vault); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: solana_program::pubkey::Pubkey) -> &mut Self { + self.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn nonce(&mut self, nonce: u64) -> &mut Self { + self.nonce = Some(nonce); + self + } + #[inline(always)] + pub fn amount_to_transfer(&mut self, amount_to_transfer: u64) -> &mut Self { + self.amount_to_transfer = Some(amount_to_transfer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = Settle { + global_account: self.global_account.expect("global_account is not set"), + user_account: self.user_account.expect("user_account is not set"), + user: self.user.expect("user is not set"), + treasury: self.treasury.expect("treasury is not set"), + lock_account: self.lock_account.expect("lock_account is not set"), + vault: self.vault.expect("vault is not set"), + bot: self.bot.expect("bot is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = SettleInstructionArgs { + nonce: self.nonce.clone().expect("nonce is not set"), + amount_to_transfer: self + .amount_to_transfer + .clone() + .expect("amount_to_transfer is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `settle` CPI accounts. +pub struct SettleCpiAccounts<'a, 'b> { + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub treasury: &'b solana_program::account_info::AccountInfo<'a>, + + pub lock_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `settle` CPI instruction. +pub struct SettleCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub global_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub treasury: &'b solana_program::account_info::AccountInfo<'a>, + + pub lock_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub bot: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: SettleInstructionArgs, +} + +impl<'a, 'b> SettleCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: SettleCpiAccounts<'a, 'b>, + args: SettleInstructionArgs, + ) -> Self { + Self { + __program: program, + global_account: accounts.global_account, + user_account: accounts.user_account, + user: accounts.user, + treasury: accounts.treasury, + lock_account: accounts.lock_account, + vault: accounts.vault, + bot: accounts.bot, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(9 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.global_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.treasury.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.lock_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.vault.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.bot.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = SettleInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(10 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.global_account.clone()); + account_infos.push(self.user_account.clone()); + account_infos.push(self.user.clone()); + account_infos.push(self.treasury.clone()); + account_infos.push(self.lock_account.clone()); + account_infos.push(self.vault.clone()); + account_infos.push(self.bot.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Settle` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[]` global_account +/// 1. `[writable]` user_account +/// 2. `[writable]` user +/// 3. `[writable]` treasury +/// 4. `[writable]` lock_account +/// 5. `[writable]` vault +/// 6. `[signer]` bot +/// 7. `[writable, signer]` payer +/// 8. `[]` system_program +#[derive(Clone, Debug)] +pub struct SettleCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> SettleCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(SettleCpiBuilderInstruction { + __program: program, + global_account: None, + user_account: None, + user: None, + treasury: None, + lock_account: None, + vault: None, + bot: None, + payer: None, + system_program: None, + nonce: None, + amount_to_transfer: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn global_account( + &mut self, + global_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.global_account = Some(global_account); + self + } + #[inline(always)] + pub fn user_account( + &mut self, + user_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.user = Some(user); + self + } + #[inline(always)] + pub fn treasury( + &mut self, + treasury: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.treasury = Some(treasury); + self + } + #[inline(always)] + pub fn lock_account( + &mut self, + lock_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.lock_account = Some(lock_account); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.vault = Some(vault); + self + } + #[inline(always)] + pub fn bot(&mut self, bot: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.bot = Some(bot); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn nonce(&mut self, nonce: u64) -> &mut Self { + self.instruction.nonce = Some(nonce); + self + } + #[inline(always)] + pub fn amount_to_transfer(&mut self, amount_to_transfer: u64) -> &mut Self { + self.instruction.amount_to_transfer = Some(amount_to_transfer); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = SettleInstructionArgs { + nonce: self.instruction.nonce.clone().expect("nonce is not set"), + amount_to_transfer: self + .instruction + .amount_to_transfer + .clone() + .expect("amount_to_transfer is not set"), + }; + let instruction = SettleCpi { + __program: self.instruction.__program, + + global_account: self + .instruction + .global_account + .expect("global_account is not set"), + + user_account: self + .instruction + .user_account + .expect("user_account is not set"), + + user: self.instruction.user.expect("user is not set"), + + treasury: self.instruction.treasury.expect("treasury is not set"), + + lock_account: self + .instruction + .lock_account + .expect("lock_account is not set"), + + vault: self.instruction.vault.expect("vault is not set"), + + bot: self.instruction.bot.expect("bot is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct SettleCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + global_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + user_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + user: Option<&'b solana_program::account_info::AccountInfo<'a>>, + treasury: Option<&'b solana_program::account_info::AccountInfo<'a>>, + lock_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + vault: Option<&'b solana_program::account_info::AccountInfo<'a>>, + bot: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + nonce: Option, + amount_to_transfer: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/withdraw.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/withdraw.rs new file mode 100644 index 0000000..011b156 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/instructions/withdraw.rs @@ -0,0 +1,472 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +/// Accounts. +pub struct Withdraw { + pub user_account: solana_program::pubkey::Pubkey, + + pub user: solana_program::pubkey::Pubkey, + + pub vault: solana_program::pubkey::Pubkey, + + pub payer: solana_program::pubkey::Pubkey, + + pub system_program: solana_program::pubkey::Pubkey, +} + +impl Withdraw { + pub fn instruction( + &self, + args: WithdrawInstructionArgs, + ) -> solana_program::instruction::Instruction { + self.instruction_with_remaining_accounts(args, &[]) + } + #[allow(clippy::vec_init_then_push)] + pub fn instruction_with_remaining_accounts( + &self, + args: WithdrawInstructionArgs, + remaining_accounts: &[solana_program::instruction::AccountMeta], + ) -> solana_program::instruction::Instruction { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user_account, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.user, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.vault, false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + self.payer, true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + self.system_program, + false, + )); + accounts.extend_from_slice(remaining_accounts); + let mut data = WithdrawInstructionData::new().try_to_vec().unwrap(); + let mut args = args.try_to_vec().unwrap(); + data.append(&mut args); + + solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + } + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct WithdrawInstructionData { + discriminator: [u8; 8], +} + +impl WithdrawInstructionData { + pub fn new() -> Self { + Self { + discriminator: [183, 18, 70, 156, 148, 109, 161, 34], + } + } +} + +impl Default for WithdrawInstructionData { + fn default() -> Self { + Self::new() + } +} + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct WithdrawInstructionArgs { + pub amount: u64, +} + +/// Instruction builder for `Withdraw`. +/// +/// ### Accounts: +/// +/// 0. `[writable]` user_account +/// 1. `[writable, signer]` user +/// 2. `[writable]` vault +/// 3. `[writable, signer]` payer +/// 4. `[optional]` system_program (default to `11111111111111111111111111111111`) +#[derive(Clone, Debug, Default)] +pub struct WithdrawBuilder { + user_account: Option, + user: Option, + vault: Option, + payer: Option, + system_program: Option, + amount: Option, + __remaining_accounts: Vec, +} + +impl WithdrawBuilder { + pub fn new() -> Self { + Self::default() + } + #[inline(always)] + pub fn user_account(&mut self, user_account: solana_program::pubkey::Pubkey) -> &mut Self { + self.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: solana_program::pubkey::Pubkey) -> &mut Self { + self.user = Some(user); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: solana_program::pubkey::Pubkey) -> &mut Self { + self.vault = Some(vault); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: solana_program::pubkey::Pubkey) -> &mut Self { + self.payer = Some(payer); + self + } + /// `[optional account, default to '11111111111111111111111111111111']` + #[inline(always)] + pub fn system_program(&mut self, system_program: solana_program::pubkey::Pubkey) -> &mut Self { + self.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: solana_program::instruction::AccountMeta, + ) -> &mut Self { + self.__remaining_accounts.push(account); + self + } + /// Add additional accounts to the instruction. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[solana_program::instruction::AccountMeta], + ) -> &mut Self { + self.__remaining_accounts.extend_from_slice(accounts); + self + } + #[allow(clippy::clone_on_copy)] + pub fn instruction(&self) -> solana_program::instruction::Instruction { + let accounts = Withdraw { + user_account: self.user_account.expect("user_account is not set"), + user: self.user.expect("user is not set"), + vault: self.vault.expect("vault is not set"), + payer: self.payer.expect("payer is not set"), + system_program: self + .system_program + .unwrap_or(solana_program::pubkey!("11111111111111111111111111111111")), + }; + let args = WithdrawInstructionArgs { + amount: self.amount.clone().expect("amount is not set"), + }; + + accounts.instruction_with_remaining_accounts(args, &self.__remaining_accounts) + } +} + +/// `withdraw` CPI accounts. +pub struct WithdrawCpiAccounts<'a, 'b> { + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, +} + +/// `withdraw` CPI instruction. +pub struct WithdrawCpi<'a, 'b> { + /// The program to invoke. + pub __program: &'b solana_program::account_info::AccountInfo<'a>, + + pub user_account: &'b solana_program::account_info::AccountInfo<'a>, + + pub user: &'b solana_program::account_info::AccountInfo<'a>, + + pub vault: &'b solana_program::account_info::AccountInfo<'a>, + + pub payer: &'b solana_program::account_info::AccountInfo<'a>, + + pub system_program: &'b solana_program::account_info::AccountInfo<'a>, + /// The arguments for the instruction. + pub __args: WithdrawInstructionArgs, +} + +impl<'a, 'b> WithdrawCpi<'a, 'b> { + pub fn new( + program: &'b solana_program::account_info::AccountInfo<'a>, + accounts: WithdrawCpiAccounts<'a, 'b>, + args: WithdrawInstructionArgs, + ) -> Self { + Self { + __program: program, + user_account: accounts.user_account, + user: accounts.user, + vault: accounts.vault, + payer: accounts.payer, + system_program: accounts.system_program, + __args: args, + } + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], &[]) + } + #[inline(always)] + pub fn invoke_with_remaining_accounts( + &self, + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(&[], remaining_accounts) + } + #[inline(always)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed_with_remaining_accounts(signers_seeds, &[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed_with_remaining_accounts( + &self, + signers_seeds: &[&[&[u8]]], + remaining_accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> solana_program::entrypoint::ProgramResult { + let mut accounts = Vec::with_capacity(5 + remaining_accounts.len()); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user_account.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.user.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.vault.key, + false, + )); + accounts.push(solana_program::instruction::AccountMeta::new( + *self.payer.key, + true, + )); + accounts.push(solana_program::instruction::AccountMeta::new_readonly( + *self.system_program.key, + false, + )); + remaining_accounts.iter().for_each(|remaining_account| { + accounts.push(solana_program::instruction::AccountMeta { + pubkey: *remaining_account.0.key, + is_signer: remaining_account.1, + is_writable: remaining_account.2, + }) + }); + let mut data = WithdrawInstructionData::new().try_to_vec().unwrap(); + let mut args = self.__args.try_to_vec().unwrap(); + data.append(&mut args); + + let instruction = solana_program::instruction::Instruction { + program_id: crate::BALANCE_PAYMENT_ID, + accounts, + data, + }; + let mut account_infos = Vec::with_capacity(6 + remaining_accounts.len()); + account_infos.push(self.__program.clone()); + account_infos.push(self.user_account.clone()); + account_infos.push(self.user.clone()); + account_infos.push(self.vault.clone()); + account_infos.push(self.payer.clone()); + account_infos.push(self.system_program.clone()); + remaining_accounts + .iter() + .for_each(|remaining_account| account_infos.push(remaining_account.0.clone())); + + if signers_seeds.is_empty() { + solana_program::program::invoke(&instruction, &account_infos) + } else { + solana_program::program::invoke_signed(&instruction, &account_infos, signers_seeds) + } + } +} + +/// Instruction builder for `Withdraw` via CPI. +/// +/// ### Accounts: +/// +/// 0. `[writable]` user_account +/// 1. `[writable, signer]` user +/// 2. `[writable]` vault +/// 3. `[writable, signer]` payer +/// 4. `[]` system_program +#[derive(Clone, Debug)] +pub struct WithdrawCpiBuilder<'a, 'b> { + instruction: Box>, +} + +impl<'a, 'b> WithdrawCpiBuilder<'a, 'b> { + pub fn new(program: &'b solana_program::account_info::AccountInfo<'a>) -> Self { + let instruction = Box::new(WithdrawCpiBuilderInstruction { + __program: program, + user_account: None, + user: None, + vault: None, + payer: None, + system_program: None, + amount: None, + __remaining_accounts: Vec::new(), + }); + Self { instruction } + } + #[inline(always)] + pub fn user_account( + &mut self, + user_account: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.user_account = Some(user_account); + self + } + #[inline(always)] + pub fn user(&mut self, user: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.user = Some(user); + self + } + #[inline(always)] + pub fn vault(&mut self, vault: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.vault = Some(vault); + self + } + #[inline(always)] + pub fn payer(&mut self, payer: &'b solana_program::account_info::AccountInfo<'a>) -> &mut Self { + self.instruction.payer = Some(payer); + self + } + #[inline(always)] + pub fn system_program( + &mut self, + system_program: &'b solana_program::account_info::AccountInfo<'a>, + ) -> &mut Self { + self.instruction.system_program = Some(system_program); + self + } + #[inline(always)] + pub fn amount(&mut self, amount: u64) -> &mut Self { + self.instruction.amount = Some(amount); + self + } + /// Add an additional account to the instruction. + #[inline(always)] + pub fn add_remaining_account( + &mut self, + account: &'b solana_program::account_info::AccountInfo<'a>, + is_writable: bool, + is_signer: bool, + ) -> &mut Self { + self.instruction + .__remaining_accounts + .push((account, is_writable, is_signer)); + self + } + /// Add additional accounts to the instruction. + /// + /// Each account is represented by a tuple of the `AccountInfo`, a `bool` indicating whether the account is writable or not, + /// and a `bool` indicating whether the account is a signer or not. + #[inline(always)] + pub fn add_remaining_accounts( + &mut self, + accounts: &[( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )], + ) -> &mut Self { + self.instruction + .__remaining_accounts + .extend_from_slice(accounts); + self + } + #[inline(always)] + pub fn invoke(&self) -> solana_program::entrypoint::ProgramResult { + self.invoke_signed(&[]) + } + #[allow(clippy::clone_on_copy)] + #[allow(clippy::vec_init_then_push)] + pub fn invoke_signed( + &self, + signers_seeds: &[&[&[u8]]], + ) -> solana_program::entrypoint::ProgramResult { + let args = WithdrawInstructionArgs { + amount: self.instruction.amount.clone().expect("amount is not set"), + }; + let instruction = WithdrawCpi { + __program: self.instruction.__program, + + user_account: self + .instruction + .user_account + .expect("user_account is not set"), + + user: self.instruction.user.expect("user is not set"), + + vault: self.instruction.vault.expect("vault is not set"), + + payer: self.instruction.payer.expect("payer is not set"), + + system_program: self + .instruction + .system_program + .expect("system_program is not set"), + __args: args, + }; + instruction.invoke_signed_with_remaining_accounts( + signers_seeds, + &self.instruction.__remaining_accounts, + ) + } +} + +#[derive(Clone, Debug)] +struct WithdrawCpiBuilderInstruction<'a, 'b> { + __program: &'b solana_program::account_info::AccountInfo<'a>, + user_account: Option<&'b solana_program::account_info::AccountInfo<'a>>, + user: Option<&'b solana_program::account_info::AccountInfo<'a>>, + vault: Option<&'b solana_program::account_info::AccountInfo<'a>>, + payer: Option<&'b solana_program::account_info::AccountInfo<'a>>, + system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>, + amount: Option, + /// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`. + __remaining_accounts: Vec<( + &'b solana_program::account_info::AccountInfo<'a>, + bool, + bool, + )>, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/mod.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/mod.rs new file mode 100644 index 0000000..6050d86 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/mod.rs @@ -0,0 +1,14 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub mod accounts; +pub mod errors; +pub mod instructions; +pub mod programs; +pub mod types; + +pub(crate) use programs::*; diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/programs.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/programs.rs new file mode 100644 index 0000000..3d9abc8 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/programs.rs @@ -0,0 +1,11 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use solana_program::{pubkey, pubkey::Pubkey}; + +/// `balance_payment` program ID. +pub const BALANCE_PAYMENT_ID: Pubkey = pubkey!("GguVKxU88NUe3GLtns7Uaa6a8Pjb9USKq3WD1rjZnPS9"); diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/types/e_d25519_recover_info.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/types/e_d25519_recover_info.rs new file mode 100644 index 0000000..ebaa398 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/types/e_d25519_recover_info.rs @@ -0,0 +1,19 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +use borsh::BorshDeserialize; +use borsh::BorshSerialize; + +#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct ED25519RecoverInfo { + #[cfg_attr(feature = "serde", serde(with = "serde_with::As::"))] + pub signature: [u8; 64], + #[cfg_attr(feature = "serde", serde(with = "serde_with::As::"))] + pub payload: [u8; 64], + pub deadline: i64, +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/generated/types/mod.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/types/mod.rs new file mode 100644 index 0000000..1d11556 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/generated/types/mod.rs @@ -0,0 +1,10 @@ +//! This code was AUTOGENERATED using the codama library. +//! Please DO NOT EDIT THIS FILE, instead use visitors +//! to add features, then rerun codama to update it. +//! +//! +//! + +pub(crate) mod r#e_d25519_recover_info; + +pub use self::r#e_d25519_recover_info::*; diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/lib.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/lib.rs new file mode 100644 index 0000000..92979fb --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/lib.rs @@ -0,0 +1,293 @@ +#[allow(clippy::all)] +#[allow(warnings, unused)] +#[rustfmt::skip] +mod generated; + +mod error; +mod verify; + +use std::time::Duration; +use std::time::SystemTime; +use std::time::UNIX_EPOCH; + +pub use error::Error; +use generated::accounts::GlobalAccount; +use generated::accounts::UserAccount; +use generated::instructions::Lock; +use generated::instructions::LockInstructionArgs; +use generated::instructions::Pay; +use generated::instructions::PayInstructionArgs; +use generated::instructions::Settle; +use generated::instructions::SettleInstructionArgs; +use generated::programs::BALANCE_PAYMENT_ID; +use generated::types::ED25519RecoverInfo; +use solana_client::nonblocking::rpc_client::RpcClient; +use solana_program::pubkey::Pubkey; +use solana_sdk::bs58; +use solana_sdk::commitment_config::CommitmentConfig; +use solana_sdk::keccak; +use solana_sdk::signature::Keypair; +use solana_sdk::signer::EncodableKey; +use solana_sdk::signer::Signer; +use solana_sdk::system_program; +use solana_sdk::transaction::Transaction; +use verify::verify_signature; + +const SIGN_MESSAGE_PREFIX: &[u8; 31] = b"DePHY vending machine/Example:\n"; + +fn get_client(url: &str) -> RpcClient { + let timeout = Duration::from_secs(10); + let commitment_config = CommitmentConfig::processed(); + let confirm_transaction_initial_timeout = Duration::from_secs(10); + RpcClient::new_with_timeouts_and_commitment( + url.to_string(), + timeout, + commitment_config, + confirm_transaction_initial_timeout, + ) +} + +pub async fn check_eligible( + rpc_url: &str, + user: &str, + nonce: u64, + amount: u64, + recover_info: &str, +) -> Result { + let user: Pubkey = user.parse()?; + let recover_info: ED25519RecoverInfo = serde_json::from_str(recover_info)?; + + let client = get_client(rpc_url); + + let user_account_pubkey = + Pubkey::find_program_address(&[b"USER", user.as_ref()], &BALANCE_PAYMENT_ID).0; + let user_account_data = client.get_account_data(&user_account_pubkey).await?; + let user_account = UserAccount::from_bytes(&user_account_data)?; + + // 0. check nonce + if user_account.nonce != nonce { + tracing::error!( + "Nonce mismatch: expected {}, got {}", + nonce, + user_account.nonce + ); + return Ok(false); + } + + // 1. concat message + let message = { + let mut data = recover_info.payload.to_vec(); + data.extend_from_slice(&user_account.nonce.to_le_bytes()); + data.extend_from_slice(&recover_info.deadline.to_le_bytes()); + data + }; + + // 2. calc message hash + let message_hash = { + let mut hasher = keccak::Hasher::default(); + hasher.hash(&message); + hasher.result().to_bytes() + }; + + // 3. generate digest + let digest = { + let mut data = SIGN_MESSAGE_PREFIX.to_vec(); + data.extend_from_slice(bs58::encode(&message_hash).into_string().as_bytes()); + data + }; + + // 4. verify signature + let valid = verify_signature(&user, &recover_info.signature, &digest) + .map_err(|e| { + tracing::error!("Signature verification failed: {:?}", e); + e + }) + .is_ok(); + + if !valid { + tracing::error!("Invalid signature"); + return Ok(false); + } + + // 5. check signature expiration + let current_timestamp = SystemTime::now() + .duration_since(UNIX_EPOCH) + .unwrap() + .as_secs() as i64; + + if current_timestamp >= recover_info.deadline { + tracing::error!("Signature expired: deadline {}", recover_info.deadline); + return Ok(false); + } + + // 6. check user vault balance + let vault_pubkey = + Pubkey::find_program_address(&[b"VAULT", user.as_ref()], &BALANCE_PAYMENT_ID).0; + let vault_balance = client.get_account(&vault_pubkey).await?.lamports; + + if vault_balance - user_account.locked_amount < amount { + tracing::error!( + "Insufficient funds: available {}, required {}", + vault_balance - user_account.locked_amount, + amount + ); + return Ok(false); + } + + tracing::info!("User is eligible"); + Ok(true) +} + +pub async fn lock( + rpc_url: &str, + keypair_path: &str, + user: &str, + amount: u64, + recover_info: &str, +) -> Result { + let user: Pubkey = user.parse()?; + let recover_info: ED25519RecoverInfo = serde_json::from_str(recover_info)?; + + let bot = Keypair::read_from_file(keypair_path).map_err(Error::KeypairReadFailed)?; + let payer = bot.insecure_clone(); + + let client = get_client(rpc_url); + + let user_account_pubkey = + Pubkey::find_program_address(&[b"USER", user.as_ref()], &BALANCE_PAYMENT_ID).0; + let user_account_data = client.get_account_data(&user_account_pubkey).await?; + let user_account = UserAccount::from_bytes(&user_account_data)?; + + let lock_instruction = Lock { + global_account: Pubkey::find_program_address(&[b"GLOBAL"], &BALANCE_PAYMENT_ID).0, + user_account: user_account_pubkey, + user, + lock_account: Pubkey::find_program_address( + &[b"LOCK", user.as_ref(), &user_account.nonce.to_le_bytes()], + &BALANCE_PAYMENT_ID, + ) + .0, + vault: Pubkey::find_program_address(&[b"VAULT", user.as_ref()], &BALANCE_PAYMENT_ID).0, + bot: bot.pubkey(), + payer: payer.pubkey(), + system_program: system_program::id(), + }; + + let latest_block = client.get_latest_blockhash().await?; + + let transaction = Transaction::new_signed_with_payer( + &[lock_instruction.instruction(LockInstructionArgs { + amount, + recover_info, + })], + Some(&payer.pubkey()), + &[&bot, &payer], + latest_block, + ); + + let signature = client.send_and_confirm_transaction(&transaction).await?; + + Ok(signature.to_string()) +} + +pub async fn settle( + rpc_url: &str, + keypair_path: &str, + user: &str, + nonce: u64, + amount_to_transfer: u64, +) -> Result { + let user: Pubkey = user.parse()?; + + let bot = Keypair::read_from_file(keypair_path).map_err(Error::KeypairReadFailed)?; + let payer = bot.insecure_clone(); + + let client = get_client(rpc_url); + + let global_account_pubkey = Pubkey::find_program_address(&[b"GLOBAL"], &BALANCE_PAYMENT_ID).0; + let global_account_data = client.get_account_data(&global_account_pubkey).await?; + let global_account: GlobalAccount = GlobalAccount::from_bytes(&global_account_data)?; + let treasury = global_account.treasury; + + let latest_block = client.get_latest_blockhash().await?; + + let settle_instruction = Settle { + global_account: global_account_pubkey, + user_account: Pubkey::find_program_address(&[b"USER", user.as_ref()], &BALANCE_PAYMENT_ID) + .0, + user, + treasury, + lock_account: Pubkey::find_program_address( + &[b"LOCK", user.as_ref(), &nonce.to_le_bytes()], + &BALANCE_PAYMENT_ID, + ) + .0, + vault: Pubkey::find_program_address(&[b"VAULT", user.as_ref()], &BALANCE_PAYMENT_ID).0, + bot: bot.pubkey(), + payer: payer.pubkey(), + system_program: system_program::id(), + }; + + let transaction = Transaction::new_signed_with_payer( + &[settle_instruction.instruction(SettleInstructionArgs { + nonce, + amount_to_transfer, + })], + Some(&payer.pubkey()), + &[&bot, &payer], + latest_block, + ); + + let signature = client.send_and_confirm_transaction(&transaction).await?; + + Ok(signature.to_string()) +} + +pub async fn pay( + rpc_url: &str, + keypair_path: &str, + user: &str, + amount_to_transfer: u64, + recover_info: &str, +) -> Result { + let user: Pubkey = user.parse()?; + let recover_info: ED25519RecoverInfo = serde_json::from_str(recover_info)?; + + let bot = Keypair::read_from_file(keypair_path).map_err(Error::KeypairReadFailed)?; + let payer = bot.insecure_clone(); + + let client = get_client(rpc_url); + + let global_account_pubkey = Pubkey::find_program_address(&[b"GLOBAL"], &BALANCE_PAYMENT_ID).0; + let global_account_data = client.get_account_data(&global_account_pubkey).await?; + let global_account: GlobalAccount = GlobalAccount::from_bytes(&global_account_data)?; + let treasury = global_account.treasury; + + let latest_block = client.get_latest_blockhash().await?; + + let pay_instruction = Pay { + global_account: global_account_pubkey, + user_account: Pubkey::find_program_address(&[b"USER", user.as_ref()], &BALANCE_PAYMENT_ID) + .0, + user, + treasury, + vault: Pubkey::find_program_address(&[b"VAULT", user.as_ref()], &BALANCE_PAYMENT_ID).0, + bot: bot.pubkey(), + payer: payer.pubkey(), + system_program: system_program::id(), + }; + + let transaction = Transaction::new_signed_with_payer( + &[pay_instruction.instruction(PayInstructionArgs { + amount_to_transfer, + recover_info, + })], + Some(&payer.pubkey()), + &[&bot, &payer], + latest_block, + ); + + let signature = client.send_and_confirm_transaction(&transaction).await?; + + Ok(signature.to_string()) +} diff --git a/dephy-vending_machine-examples/balance-payment-sdk/src/verify.rs b/dephy-vending_machine-examples/balance-payment-sdk/src/verify.rs new file mode 100644 index 0000000..453165e --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment-sdk/src/verify.rs @@ -0,0 +1,61 @@ +use arrayref::array_ref; +use curve25519_dalek::scalar::Scalar; +use sha2::Digest; +use solana_program::pubkey::Pubkey; +use solana_zk_token_sdk::curve25519::edwards::multiply_edwards; +use solana_zk_token_sdk::curve25519::edwards::subtract_edwards; +use solana_zk_token_sdk::curve25519::edwards::validate_edwards; +use solana_zk_token_sdk::curve25519::edwards::PodEdwardsPoint; +use solana_zk_token_sdk::curve25519::scalar::PodScalar; + +use crate::Error; + +// funny number +const EDWARDS_BASE_POINT: PodEdwardsPoint = PodEdwardsPoint([ + 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +]); + +pub fn verify_signature( + pubkey: &Pubkey, + signature: &[u8; 64], + message: &[u8], +) -> Result { + let a = PodEdwardsPoint(pubkey.to_bytes()); + let r = PodEdwardsPoint(*array_ref![signature, 0, 32]); + if !validate_edwards(&a) { + return Err(Error::SignatureVerificationFailed( + "Pubkey is not a valid EdwardsPoint".to_string(), + )); + } + if !validate_edwards(&r) { + return Err(Error::SignatureVerificationFailed( + "Signature R is not a valid EdwardsPoint".to_string(), + )); + } + + let s = array_ref![signature, 32, 32]; + let s_scalar = Scalar::from_bytes_mod_order(*s); + let s_scalar = PodScalar(s_scalar.to_bytes()); + + let mut hasher = sha2::Sha512::new(); + // R || A || M + hasher.update(r.0); + hasher.update(a.0); + hasher.update(message); + let hash_bytes = hasher.finalize(); + let hash_array = array_ref![hash_bytes, 0, 64]; + let h_scalar = Scalar::from_bytes_mod_order_wide(hash_array); + let h_scalar = PodScalar(h_scalar.to_bytes()); + + let s_b = multiply_edwards(&s_scalar, &EDWARDS_BASE_POINT).ok_or( + Error::SignatureVerificationFailed("Failed to multiply S*B".to_string()), + )?; + let h_a = multiply_edwards(&h_scalar, &a).ok_or(Error::SignatureVerificationFailed( + "Failed to multiply H*A".to_string(), + ))?; + let r_prime = subtract_edwards(&s_b, &h_a).ok_or(Error::SignatureVerificationFailed( + "Failed to subtract HA from SB".to_string(), + ))?; + Ok(r_prime == r) +} diff --git a/dephy-vending_machine-examples/balance-payment/Anchor.toml b/dephy-vending_machine-examples/balance-payment/Anchor.toml new file mode 100644 index 0000000..7eb2421 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/Anchor.toml @@ -0,0 +1,19 @@ +[toolchain] + +[features] +resolution = true +skip-lint = false + +[programs.localnet] +balance_payment = "GguVKxU88NUe3GLtns7Uaa6a8Pjb9USKq3WD1rjZnPS9" + +[registry] +url = "https://api.apr.dev" + +[provider] +cluster = "Localnet" +wallet = "~/.config/solana/id.json" + +[scripts] +cli = "bun run -b scripts/cli.ts" +test = "bun run -b ts-mocha -p ./tsconfig.json -t 1000000 tests/**/*.ts" diff --git a/dephy-vending_machine-examples/balance-payment/Cargo.lock b/dephy-vending_machine-examples/balance-payment/Cargo.lock new file mode 100644 index 0000000..0afd5be --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/Cargo.lock @@ -0,0 +1,2126 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "aes-gcm-siv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d" +dependencies = [ + "aead", + "aes", + "cipher", + "ctr", + "polyval", + "subtle", + "zeroize", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anchor-attribute-access-control" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37013051defd745a5437d6842bd404e5480e14ad4e4f0441dd9a81a4b9aea1d6" +dependencies = [ + "anchor-syn", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-account" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92db0f793e924e18462b3fac53c5759a8248649a8072788b5e88a4af714998c8" +dependencies = [ + "anchor-syn", + "bs58 0.5.1", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-constant" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a98126ebfc96d6248899caadc9ea7c2403420c4f5c994e541802bce9f423674" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-error" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8a4dcb403f872fbcd0910fc39a3e05bb6c43a8399f915a1878e62eb680fbb23" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-event" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "420d651b2703ccff86f6c4b7c394140cb85049787c078a5f8280506121d48065" +dependencies = [ + "anchor-syn", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-attribute-program" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d258f3a9f47db7f4199888df0ee67e42b960a7acb8f5c336b585d4eb243b9665" +dependencies = [ + "anchor-lang-idl", + "anchor-syn", + "anyhow", + "bs58 0.5.1", + "heck", + "proc-macro2", + "quote", + "serde_json", + "syn 1.0.109", +] + +[[package]] +name = "anchor-derive-accounts" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "097147501de51105d8dbdad9bd5a96a1b17ecbb2cee9f200d6167031372eab3b" +dependencies = [ + "anchor-syn", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-derive-serde" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5a24721da4ed67f0a1391cac27ea7e51c255cbd94cdcc6728a0aa56227628d0" +dependencies = [ + "anchor-syn", + "borsh-derive-internal", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-derive-space" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41986f84d238a2f7a807f3a98da5df0e97ebe23f29f7d67b8cdd4fd80bc1ba1" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "anchor-lang" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eba81a0543fee1b7b610fe9ebedbae6a14e8d3e85a6a6dd48871d48a08880195" +dependencies = [ + "anchor-attribute-access-control", + "anchor-attribute-account", + "anchor-attribute-constant", + "anchor-attribute-error", + "anchor-attribute-event", + "anchor-attribute-program", + "anchor-derive-accounts", + "anchor-derive-serde", + "anchor-derive-space", + "anchor-lang-idl", + "base64 0.21.7", + "bincode", + "borsh 0.10.4", + "bytemuck", + "solana-program", + "thiserror", +] + +[[package]] +name = "anchor-lang-idl" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32e8599d21995f68e296265aa5ab0c3cef582fd58afec014d01bd0bce18a4418" +dependencies = [ + "anchor-lang-idl-spec", + "anyhow", + "heck", + "regex", + "serde", + "serde_json", + "sha2 0.10.8", +] + +[[package]] +name = "anchor-lang-idl-spec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdf143115440fe621bdac3a29a1f7472e09f6cd82b2aa569429a0c13f103838" +dependencies = [ + "anyhow", + "serde", +] + +[[package]] +name = "anchor-syn" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "564685b759db12a2424d1b2688cfdf0fec26a023813bc461274754fb0e5d97b0" +dependencies = [ + "anyhow", + "bs58 0.5.1", + "cargo_toml", + "heck", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2 0.10.8", + "syn 1.0.109", + "thiserror", +] + +[[package]] +name = "anyhow" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" + +[[package]] +name = "ark-bn254" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a22f4561524cd949590d78d7d4c5df8f592430d221f7f3c9497bbafd8972120f" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-std", +] + +[[package]] +name = "ark-ec" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "defd9a439d56ac24968cca0571f598a61bc8c55f71d50a89cda591cb750670ba" +dependencies = [ + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", + "itertools 0.10.5", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "derivative", + "digest 0.10.7", + "itertools 0.10.5", + "num-bigint", + "num-traits", + "paste", + "rustc_version", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" +dependencies = [ + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-ff-macros" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-poly" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d320bfc44ee185d899ccbadfa8bc31aab923ce1558716e1997a1e74057fe86bf" +dependencies = [ + "ark-ff", + "ark-serialize", + "ark-std", + "derivative", + "hashbrown 0.13.2", +] + +[[package]] +name = "ark-serialize" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "digest 0.10.7", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae3281bc6d0fd7e549af32b52511e1302185bd688fd3359fa36423346ff682ea" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "ark-std" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayref" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "balance-payment" +version = "0.1.0" +dependencies = [ + "anchor-lang", + "anyhow", + "arrayref", + "bs58 0.4.0", + "curve25519-dalek 4.1.3", + "sha2 0.10.8", + "solana-zk-token-sdk", +] + +[[package]] +name = "base64" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +dependencies = [ + "serde", +] + +[[package]] +name = "blake3" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8ee0c1824c4dea5b5f81736aff91bae041d2c07ee1192bec91054e10e3e601e" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "digest 0.10.7", +] + +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" + +[[package]] +name = "borsh" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" +dependencies = [ + "borsh-derive 0.10.4", + "hashbrown 0.13.2", +] + +[[package]] +name = "borsh" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5430e3be710b68d984d1391c854eb431a9d548640711faa54eecb1df93db91cc" +dependencies = [ + "borsh-derive 1.5.5", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + +[[package]] +name = "borsh-derive" +version = "1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8b668d39970baad5356d7c83a86fee3a539e6f93bf6764c97368243e17a0487" +dependencies = [ + "once_cell", + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "borsh-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bs58" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" + +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bv" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8834bb1d8ee5dc048ee3124f2c7c1afcc6bc9aed03f11e9dfd8c69470a5db340" +dependencies = [ + "feature-probe", + "serde", +] + +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" + +[[package]] +name = "bytemuck_derive" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fa76293b4f7bb636ab88fd78228235b5248b4d05cc589aed610f954af5d7c7a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cargo_toml" +version = "0.19.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a98356df42a2eb1bd8f1793ae4ee4de48e384dd974ce5eac8eee802edb7492be" +dependencies = [ + "serde", + "toml 0.8.19", +] + +[[package]] +name = "cc" +version = "1.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chrono" +version = "0.4.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" +dependencies = [ + "num-traits", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "console_log" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89f72f65e8501878b8a004d5a1afb780987e2ce2b4532c562e367a72c57499f" +dependencies = [ + "log", + "web-sys", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctr" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +dependencies = [ + "cipher", +] + +[[package]] +name = "curve25519-dalek" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f9d052967f590a76e62eb387bd0bbb1b000182c3cefe5364db6b7211651bc0" +dependencies = [ + "byteorder", + "digest 0.9.0", + "rand_core 0.5.1", + "serde", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "fiat-crypto", + "rustc_version", + "subtle", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.96", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "derivation-path" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e5c37193a1db1d8ed868c03ec7b152175f26160a5b740e5e484143877e0adf0" + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", + "subtle", +] + +[[package]] +name = "ed25519" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91cff35c70bba8a626e3185d8cd48cc11b5437e1a5bcd15b9b5fa3c64b6dfee7" +dependencies = [ + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762bae6dcaf24c4c84667b8579785430908723d5c889f469d76a41d59cc7a9d" +dependencies = [ + "curve25519-dalek 3.2.1", + "ed25519", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "zeroize", +] + +[[package]] +name = "ed25519-dalek-bip32" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d2be62a4061b872c8c0873ee4fc6f101ce7b889d039f019c5fa2af471a59908" +dependencies = [ + "derivation-path", + "ed25519-dalek", + "hmac 0.12.1", + "sha2 0.10.8", +] + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "feature-probe" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "835a3dc7d1ec9e75e2b5fb4ba75396837112d2060b03f7d43bc1897c7f7211da" + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "serde", + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + +[[package]] +name = "heck" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac", + "digest 0.9.0", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "hmac-drbg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" +dependencies = [ + "digest 0.9.0", + "generic-array", + "hmac 0.8.1", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "libsecp256k1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9d220bc1feda2ac231cb78c3d26f27676b8cf82c96971f7aeef3d0cf2797c73" +dependencies = [ + "arrayref", + "base64 0.12.3", + "digest 0.9.0", + "hmac-drbg", + "libsecp256k1-core", + "libsecp256k1-gen-ecmult", + "libsecp256k1-gen-genmult", + "rand 0.7.3", + "serde", + "sha2 0.9.9", + "typenum", +] + +[[package]] +name = "libsecp256k1-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f6ab710cec28cef759c5f18671a27dae2a5f952cdaaee1d8e2908cb2478a80" +dependencies = [ + "crunchy", + "digest 0.9.0", + "subtle", +] + +[[package]] +name = "libsecp256k1-gen-ecmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccab96b584d38fac86a83f07e659f0deafd0253dc096dab5a36d53efe653c5c3" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "libsecp256k1-gen-genmult" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67abfe149395e3aa1c48a2beb32b068e2334402df8181f818d3aee2b304c4f5d" +dependencies = [ + "libsecp256k1-core", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "memmap2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +dependencies = [ + "libc", +] + +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate 3.2.0", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "polyval" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" +dependencies = [ + "cfg-if", + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml 0.5.11", +] + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "qstring" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d464fae65fff2680baf48019211ce37aaec0c78e9264c84a3e484717f965104e" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.15", +] + +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "serde_json" +version = "1.0.137" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_with" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest 0.10.7", +] + +[[package]] +name = "sha3" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +dependencies = [ + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug", +] + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest 0.10.7", + "keccak", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "solana-curve25519" +version = "2.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53061d8df8e7672af6b7130a934d6004a677e8f18526dce55da8f952f2ed37" +dependencies = [ + "bytemuck", + "bytemuck_derive", + "curve25519-dalek 3.2.1", + "solana-program", + "thiserror", +] + +[[package]] +name = "solana-program" +version = "2.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd54adccd5d91cdfb71e3aeadb77d7b95db15857f0457c944e45794f1d547c9d" +dependencies = [ + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-serialize", + "base64 0.22.1", + "bincode", + "bitflags", + "blake3", + "borsh 0.10.4", + "borsh 1.5.5", + "bs58 0.5.1", + "bv", + "bytemuck", + "bytemuck_derive", + "console_error_panic_hook", + "console_log", + "curve25519-dalek 3.2.1", + "getrandom 0.2.15", + "js-sys", + "lazy_static", + "libsecp256k1", + "log", + "memoffset", + "num-bigint", + "num-derive", + "num-traits", + "parking_lot", + "rand 0.8.5", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "sha2 0.10.8", + "sha3 0.10.8", + "solana-sdk-macro", + "thiserror", + "wasm-bindgen", +] + +[[package]] +name = "solana-sdk" +version = "2.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaeeedba53edf184c58b22f9f0701f821fd5d9161423036e168bcb5b3d78d2b3" +dependencies = [ + "bincode", + "bitflags", + "borsh 1.5.5", + "bs58 0.5.1", + "bytemuck", + "bytemuck_derive", + "byteorder", + "chrono", + "derivation-path", + "digest 0.10.7", + "ed25519-dalek", + "ed25519-dalek-bip32", + "generic-array", + "getrandom 0.1.16", + "hmac 0.12.1", + "itertools 0.12.1", + "js-sys", + "lazy_static", + "libsecp256k1", + "log", + "memmap2", + "num_enum", + "pbkdf2", + "qstring", + "rand 0.7.3", + "rand 0.8.5", + "rustc_version", + "rustversion", + "serde", + "serde_bytes", + "serde_derive", + "serde_json", + "serde_with", + "sha2 0.10.8", + "sha3 0.10.8", + "siphasher", + "solana-program", + "solana-sdk-macro", + "thiserror", + "uriparse", + "wasm-bindgen", +] + +[[package]] +name = "solana-sdk-macro" +version = "2.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2b11eb2ebad5e1dd244bd0058bb004d972e7b16834d7ff241c35e3fceda8ee" +dependencies = [ + "bs58 0.5.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.96", +] + +[[package]] +name = "solana-zk-token-sdk" +version = "2.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e6f619f88203c99438beefe0e1193da075d118961392055d7ef13f1d5cde40b" +dependencies = [ + "aes-gcm-siv", + "base64 0.22.1", + "bincode", + "bytemuck", + "bytemuck_derive", + "byteorder", + "curve25519-dalek 3.2.1", + "itertools 0.12.1", + "lazy_static", + "merlin", + "num-derive", + "num-traits", + "rand 0.7.3", + "serde", + "serde_derive", + "serde_json", + "sha3 0.9.1", + "solana-curve25519", + "solana-program", + "solana-sdk", + "subtle", + "thiserror", + "zeroize", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.96" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "tinyvec" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "uriparse" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0200d0fc04d809396c2ad43f3c95da3582a2556eba8d453c1087f4120ee352ff" +dependencies = [ + "fnv", + "lazy_static", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.96", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" +dependencies = [ + "memchr", +] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + +[[package]] +name = "zeroize" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4756f7db3f7b5574938c3eb1c117038b8e07f95ee6718c0efad4ac21508f1efd" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] diff --git a/dephy-vending_machine-examples/balance-payment/Cargo.toml b/dephy-vending_machine-examples/balance-payment/Cargo.toml new file mode 100644 index 0000000..68da9dd --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/Cargo.toml @@ -0,0 +1,13 @@ +[workspace] +members = ["programs/*"] +resolver = "2" + +[profile.release] +overflow-checks = true +lto = "fat" +codegen-units = 1 + +[profile.release.build-override] +opt-level = 3 +incremental = false +codegen-units = 1 diff --git a/dephy-vending_machine-examples/balance-payment/README.md b/dephy-vending_machine-examples/balance-payment/README.md new file mode 100644 index 0000000..ceb2a95 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/README.md @@ -0,0 +1,96 @@ +# Balance Payment Program + +This project is a Solana program built using the Anchor framework. +It allows users to deposit, withdraw, lock, and settle funds, as well as make payments to a treasury account. +The program is designed to be used in conjunction with a bot and a treasury account, which are managed by an authority. + +## Getting Started + +### Prerequisites + +Before you begin, ensure you have the following installed: + +- [Node.js](https://nodejs.org) (v20 or higher) +- [Bun](https://bun.sh/docs/installation) +- [Solana & Anchor](https://solana.com/docs/intro/installation) + +### Installation + +```bash +bun install +``` + +## Compiling the Program + +To compile the program, run: + +```bash +anchor build +``` + +This command compiles the Solana program and generates the necessary artifacts. + +## Deploying the Program Locally + +To deploy the program to a local Solana validator, follow these steps: + +1. **Start a local Solana validator:** + +```bash +solana-test-validator --reset +``` + +This command starts a local Solana blockchain instance. + +2. **Ensure your Solana CLI is configured to use the local validator:** + +```bash +solana config set --url http://localhost:8899 +``` + +3. **Airdrop SOL to your local wallet:** + +```bash +solana airdrop 2 +solana airdrop 2 9nyhqLqmbWoUuNXA1XCVnEqiS9UWvxFYa1yynVVFzR4D +``` + +4. **Deploy the program to the local validator:** + +```bash +solana program deploy ./target/deploy/balance_payment.so --program-id ./programs/balance-payment/keypair.json +``` + +This command will deploy the program to the local Solana validator and output the program ID. + +# Initialize the Program + +Initializes the program with an authority, treasury, and bot. + +```bash +anchor run cli -- initialize --authority --treasury --bot 9nyhqLqmbWoUuNXA1XCVnEqiS9UWvxFYa1yynVVFzR4D +``` + +- `--authority`: The public key of the authority. +- `--treasury`: The public key of the treasury account. +- `--bot`: The public key of the bot account. + +# App Demo + +The `app` folder contains a demo application that interacts with the Balance Payment program. To run the demo: + +- Navigate to the `app` directory: +```bash +cd app +``` +- Install dependencies: +```bash +bun install +``` +- Start the development server: +```bash +bun run dev +``` +- Open your browser and navigate to `http://localhost:5173` to view the demo. + +This demo provides a user-friendly interface to interact with the Balance Payment program, enabling users to manage funds and simulate charging sessions. diff --git a/dephy-vending_machine-examples/balance-payment/app/.env.example b/dephy-vending_machine-examples/balance-payment/app/.env.example new file mode 100644 index 0000000..600ff62 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/.env.example @@ -0,0 +1,2 @@ +VITE_RELAY_ENDPOINT= +VITE_NETWORK= diff --git a/dephy-vending_machine-examples/balance-payment/app/.gitignore b/dephy-vending_machine-examples/balance-payment/app/.gitignore new file mode 100644 index 0000000..33c24ce --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/.gitignore @@ -0,0 +1,25 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +/tmp diff --git a/dephy-vending_machine-examples/balance-payment/app/.prettierignore b/dephy-vending_machine-examples/balance-payment/app/.prettierignore new file mode 100644 index 0000000..8d646b0 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/.prettierignore @@ -0,0 +1,8 @@ +# Add files here to ignore them from prettier formatting +/.yarn +/coverage +/dist +/tmp +package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/dephy-vending_machine-examples/balance-payment/app/.prettierrc b/dephy-vending_machine-examples/balance-payment/app/.prettierrc new file mode 100644 index 0000000..f8fb56b --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/.prettierrc @@ -0,0 +1,7 @@ +{ + "singleQuote": true, + "printWidth": 120, + "semi": false, + "trailingComma": "all", + "arrowParens": "always" +} diff --git a/dephy-vending_machine-examples/balance-payment/app/LICENSE b/dephy-vending_machine-examples/balance-payment/app/LICENSE new file mode 100644 index 0000000..f79b9ea --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022-2024 Solana Foundation + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/dephy-vending_machine-examples/balance-payment/app/README.md b/dephy-vending_machine-examples/balance-payment/app/README.md new file mode 100644 index 0000000..7726ada --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/README.md @@ -0,0 +1,7 @@ +Balance payment dApp +==== + +## Run + +- `bun i` +- `bun run dev` diff --git a/dephy-vending_machine-examples/balance-payment/app/eslint.config.js b/dephy-vending_machine-examples/balance-payment/app/eslint.config.js new file mode 100644 index 0000000..05c6758 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/eslint.config.js @@ -0,0 +1,25 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], + }, + }, +) diff --git a/dephy-vending_machine-examples/balance-payment/app/index.html b/dephy-vending_machine-examples/balance-payment/app/index.html new file mode 100644 index 0000000..a5f3d4e --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/index.html @@ -0,0 +1,13 @@ + + + + + + + Balance Payment + + +
+ + + diff --git a/dephy-vending_machine-examples/balance-payment/app/package.json b/dephy-vending_machine-examples/balance-payment/app/package.json new file mode 100644 index 0000000..09f76de --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/package.json @@ -0,0 +1,58 @@ +{ + "name": "template-react-vite-tailwind-counter", + "description": "React + Vite + Tailwind + Anchor Counter program", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@coral-xyz/anchor": "^0.31.0", + "@noble/hashes": "^1.7.0", + "@solana/spl-token": "^0.4.8", + "@solana/wallet-adapter-base": "^0.9.23", + "@solana/wallet-adapter-react": "^0.15.35", + "@solana/wallet-adapter-react-ui": "^0.9.35", + "@solana/web3.js": "^1.95.3", + "@tabler/icons-react": "^3.15.0", + "@tanstack/react-query": "^5.55.2", + "bs58": "^6.0.0", + "daisyui": "^4.12.10", + "jotai": "^2.9.3", + "keccak": "^3.0.4", + "node-stdlib-browser": "^1.2.0", + "nostr-tools": "^2.10.4", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "react-hot-toast": "^2.4.1", + "react-router": "^6.26.1", + "react-router-dom": "^6.26.1", + "tailwindcss": "^3.4.10", + "uuid": "^11.0.5" + }, + "devDependencies": { + "@esbuild-plugins/node-globals-polyfill": "^0.2.3", + "@eslint/js": "^9.9.0", + "@types/jest": "^29.5.13", + "@types/keccak": "^3.0.5", + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "eslint": "^9.9.0", + "eslint-plugin-react-hooks": "^5.1.0-rc.0", + "eslint-plugin-react-refresh": "^0.4.9", + "globals": "^15.9.0", + "jest": "^29.7.0", + "prettier": "^3.3.3", + "ts-jest": "^29.2.5", + "typescript": "^5.5.3", + "typescript-eslint": "^8.0.1", + "vite": "^5.4.1", + "vite-plugin-node-polyfills": "^0.22.0", + "vite-tsconfig-paths": "^5.0.1" + } +} diff --git a/dephy-vending_machine-examples/balance-payment/app/postcss.config.mjs b/dephy-vending_machine-examples/balance-payment/app/postcss.config.mjs new file mode 100644 index 0000000..0dc456a --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/postcss.config.mjs @@ -0,0 +1,8 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + }, +} + +export default config diff --git a/dephy-vending_machine-examples/balance-payment/app/public/logo.png b/dephy-vending_machine-examples/balance-payment/app/public/logo.png new file mode 100644 index 0000000..404e288 Binary files /dev/null and b/dephy-vending_machine-examples/balance-payment/app/public/logo.png differ diff --git a/dephy-vending_machine-examples/balance-payment/app/src/anchor/balance_payment.json b/dephy-vending_machine-examples/balance-payment/app/src/anchor/balance_payment.json new file mode 100644 index 0000000..976d2f6 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/anchor/balance_payment.json @@ -0,0 +1,818 @@ +{ + "address": "GguVKxU88NUe3GLtns7Uaa6a8Pjb9USKq3WD1rjZnPS9", + "metadata": { + "name": "balance_payment", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "deposit", + "discriminator": [ + 242, + 35, + 198, + 137, + 82, + 225, + 242, + 182 + ], + "accounts": [ + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true, + "signer": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "global_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority" + }, + { + "name": "treasury" + }, + { + "name": "bot" + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "lock", + "discriminator": [ + 21, + 19, + 208, + 43, + 237, + 62, + 255, + 87 + ], + "accounts": [ + { + "name": "global_account", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "lock_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 76, + 79, + 67, + 75 + ] + }, + { + "kind": "account", + "path": "user" + }, + { + "kind": "account", + "path": "user_account.nonce", + "account": "UserAccount" + } + ] + } + }, + { + "name": "vault", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "global_account" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "recover_info", + "type": { + "defined": { + "name": "ED25519RecoverInfo" + } + } + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "register", + "discriminator": [ + 211, + 124, + 67, + 15, + 211, + 194, + 178, + 240 + ], + "accounts": [ + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "signer": true + }, + { + "name": "vault", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "set_bot", + "discriminator": [ + 136, + 185, + 99, + 236, + 200, + 131, + 204, + 118 + ], + "accounts": [ + { + "name": "global_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority", + "signer": true, + "relations": [ + "global_account" + ] + }, + { + "name": "bot" + }, + { + "name": "payer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "set_treasury", + "discriminator": [ + 57, + 97, + 196, + 95, + 195, + 206, + 106, + 136 + ], + "accounts": [ + { + "name": "global_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority", + "signer": true, + "relations": [ + "global_account" + ] + }, + { + "name": "treasury" + }, + { + "name": "payer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "settle", + "discriminator": [ + 175, + 42, + 185, + 87, + 144, + 131, + 102, + 212 + ], + "accounts": [ + { + "name": "global_account", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "lock_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 76, + 79, + 67, + 75 + ] + }, + { + "kind": "account", + "path": "user" + }, + { + "kind": "arg", + "path": "nonce" + } + ] + } + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "global_account" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "_nonce", + "type": "u64" + }, + { + "name": "amount_to_transfer", + "type": "u64" + } + ] + }, + { + "name": "withdraw", + "discriminator": [ + 183, + 18, + 70, + 156, + 148, + 109, + 161, + 34 + ], + "accounts": [ + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true, + "signer": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "GlobalAccount", + "discriminator": [ + 129, + 105, + 124, + 171, + 189, + 42, + 108, + 69 + ] + }, + { + "name": "LockAccount", + "discriminator": [ + 223, + 64, + 71, + 124, + 255, + 86, + 118, + 192 + ] + }, + { + "name": "UserAccount", + "discriminator": [ + 211, + 33, + 136, + 16, + 186, + 110, + 242, + 127 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "Unauthorized", + "msg": "Unauthorized access." + }, + { + "code": 6001, + "name": "InsufficientFunds", + "msg": "Insufficient funds." + }, + { + "code": 6002, + "name": "SignatureFormatInvalid", + "msg": "The signature format or recovery ID is incorrect." + }, + { + "code": 6003, + "name": "SignatureRecoveryFailed", + "msg": "Failed to recover public key from signature." + }, + { + "code": 6004, + "name": "SignatureMismatch", + "msg": "The recovered public key does not match the user's public key." + }, + { + "code": 6005, + "name": "SignatureExpired", + "msg": "The signature is expired." + } + ], + "types": [ + { + "name": "ED25519RecoverInfo", + "type": { + "kind": "struct", + "fields": [ + { + "name": "signature", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "payload", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "deadline", + "type": "i64" + } + ] + } + }, + { + "name": "GlobalAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "bot", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + } + ] + } + }, + { + "name": "LockAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + } + ] + } + }, + { + "name": "UserAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "nonce", + "type": "u64" + }, + { + "name": "locked_amount", + "type": "u64" + }, + { + "name": "vault", + "type": "pubkey" + } + ] + } + } + ] +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/anchor/balance_payment.ts b/dephy-vending_machine-examples/balance-payment/app/src/anchor/balance_payment.ts new file mode 100644 index 0000000..80fbf2b --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/anchor/balance_payment.ts @@ -0,0 +1,824 @@ +/** + * Program IDL in camelCase format in order to be used in JS/TS. + * + * Note that this is only a type helper and is not the actual IDL. The original + * IDL can be found at `target/idl/balance_payment.json`. + */ +export type BalancePayment = { + "address": "GguVKxU88NUe3GLtns7Uaa6a8Pjb9USKq3WD1rjZnPS9", + "metadata": { + "name": "balancePayment", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "deposit", + "discriminator": [ + 242, + 35, + 198, + 137, + 82, + 225, + 242, + 182 + ], + "accounts": [ + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true, + "signer": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "globalAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority" + }, + { + "name": "treasury" + }, + { + "name": "bot" + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "lock", + "discriminator": [ + 21, + 19, + 208, + 43, + 237, + 62, + 255, + 87 + ], + "accounts": [ + { + "name": "globalAccount", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "lockAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 76, + 79, + 67, + 75 + ] + }, + { + "kind": "account", + "path": "user" + }, + { + "kind": "account", + "path": "user_account.nonce", + "account": "userAccount" + } + ] + } + }, + { + "name": "vault", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "globalAccount" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "recoverInfo", + "type": { + "defined": { + "name": "ed25519RecoverInfo" + } + } + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "register", + "discriminator": [ + 211, + 124, + 67, + 15, + 211, + 194, + 178, + 240 + ], + "accounts": [ + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "signer": true + }, + { + "name": "vault", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "setBot", + "discriminator": [ + 136, + 185, + 99, + 236, + 200, + 131, + 204, + 118 + ], + "accounts": [ + { + "name": "globalAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority", + "signer": true, + "relations": [ + "globalAccount" + ] + }, + { + "name": "bot" + }, + { + "name": "payer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "setTreasury", + "discriminator": [ + 57, + 97, + 196, + 95, + 195, + 206, + 106, + 136 + ], + "accounts": [ + { + "name": "globalAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority", + "signer": true, + "relations": [ + "globalAccount" + ] + }, + { + "name": "treasury" + }, + { + "name": "payer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "settle", + "discriminator": [ + 175, + 42, + 185, + 87, + 144, + 131, + 102, + 212 + ], + "accounts": [ + { + "name": "globalAccount", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "lockAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 76, + 79, + 67, + 75 + ] + }, + { + "kind": "account", + "path": "user" + }, + { + "kind": "arg", + "path": "nonce" + } + ] + } + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "globalAccount" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "nonce", + "type": "u64" + }, + { + "name": "amountToTransfer", + "type": "u64" + } + ] + }, + { + "name": "withdraw", + "discriminator": [ + 183, + 18, + 70, + 156, + 148, + 109, + 161, + 34 + ], + "accounts": [ + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true, + "signer": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "globalAccount", + "discriminator": [ + 129, + 105, + 124, + 171, + 189, + 42, + 108, + 69 + ] + }, + { + "name": "lockAccount", + "discriminator": [ + 223, + 64, + 71, + 124, + 255, + 86, + 118, + 192 + ] + }, + { + "name": "userAccount", + "discriminator": [ + 211, + 33, + 136, + 16, + 186, + 110, + 242, + 127 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "unauthorized", + "msg": "Unauthorized access." + }, + { + "code": 6001, + "name": "insufficientFunds", + "msg": "Insufficient funds." + }, + { + "code": 6002, + "name": "signatureFormatInvalid", + "msg": "The signature format or recovery ID is incorrect." + }, + { + "code": 6003, + "name": "signatureRecoveryFailed", + "msg": "Failed to recover public key from signature." + }, + { + "code": 6004, + "name": "signatureMismatch", + "msg": "The recovered public key does not match the user's public key." + }, + { + "code": 6005, + "name": "signatureExpired", + "msg": "The signature is expired." + } + ], + "types": [ + { + "name": "ed25519RecoverInfo", + "type": { + "kind": "struct", + "fields": [ + { + "name": "signature", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "payload", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "deadline", + "type": "i64" + } + ] + } + }, + { + "name": "globalAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "bot", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + } + ] + } + }, + { + "name": "lockAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + } + ] + } + }, + { + "name": "userAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "nonce", + "type": "u64" + }, + { + "name": "lockedAmount", + "type": "u64" + }, + { + "name": "vault", + "type": "pubkey" + } + ] + } + } + ] +}; diff --git a/dephy-vending_machine-examples/balance-payment/app/src/anchor/index.ts b/dephy-vending_machine-examples/balance-payment/app/src/anchor/index.ts new file mode 100644 index 0000000..3a53c24 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/anchor/index.ts @@ -0,0 +1,29 @@ +// Here we export some useful types and functions for interacting with the Anchor program. +import { AnchorProvider, Program } from '@coral-xyz/anchor' +import { Cluster, PublicKey } from '@solana/web3.js' +import BalancePaymentIDL from './balance_payment.json' +import type { BalancePayment } from './balance_payment' + +// Re-export the generated IDL and type +export { BalancePayment, BalancePaymentIDL } + +// The programId is imported from the program IDL. +export const BALANCE_PAYMENT_PROGRAM_ID = new PublicKey(BalancePaymentIDL.address) + +// This is a helper function to get the BalancePayment Anchor program. +export function getBalancePaymentProgram(provider: AnchorProvider, address?: PublicKey) { + return new Program({ ...BalancePaymentIDL, address: address ? address.toBase58() : BalancePaymentIDL.address } as BalancePayment, provider) +} + +// This is a helper function to get the program ID for the BalancePayment program depending on the cluster. +export function getBalancePaymentProgramId(cluster: Cluster) { + switch (cluster) { + case 'devnet': + case 'testnet': + // This is the program ID for the BalancePayment program on devnet and testnet. + return new PublicKey('GguVKxU88NUe3GLtns7Uaa6a8Pjb9USKq3WD1rjZnPS9') + case 'mainnet-beta': + default: + return BALANCE_PAYMENT_PROGRAM_ID + } +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/app/app-routes.tsx b/dephy-vending_machine-examples/balance-payment/app/src/app/app-routes.tsx new file mode 100644 index 0000000..2ccb66f --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/app/app-routes.tsx @@ -0,0 +1,32 @@ +import { UiLayout } from '@/components/ui/ui-layout' +import { lazy } from 'react' +import { Navigate, RouteObject, useRoutes } from 'react-router-dom' + +const AccountListFeature = lazy(() => import('../components/account/account-list-feature')) +const AccountDetailFeature = lazy(() => import('../components/account/account-detail-feature')) +const ClusterFeature = lazy(() => import('../components/cluster/cluster-feature')) +const BalancePaymentFeature = lazy(() => import('../components/balance-payment/balance-payment-feature')) +const DashboardFeature = lazy(() => import('../components/dashboard/dashboard-feature')) + +const links: { label: string; path: string }[] = [ + { label: 'Account', path: '/account' }, + { label: 'Clusters', path: '/clusters' }, + { label: 'Balance Payment Program', path: '/program' }, +] + +const routes: RouteObject[] = [ + { path: '/account/', element: }, + { path: '/account/:address', element: }, + { path: '/program', element: }, + { path: '/clusters', element: }, +] + +export function AppRoutes() { + const router = useRoutes([ + { index: true, element: }, + { path: '/dashboard', element: }, + ...routes, + { path: '*', element: }, + ]) + return {router} +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/app/app.tsx b/dephy-vending_machine-examples/balance-payment/app/src/app/app.tsx new file mode 100644 index 0000000..c161833 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/app/app.tsx @@ -0,0 +1,18 @@ +import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { ClusterProvider } from '../components/cluster/cluster-data-access' +import { SolanaProvider } from '../components/solana/solana-provider' +import { AppRoutes } from './app-routes' + +const client = new QueryClient() + +export function App() { + return ( + + + + + + + + ) +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/app/favicon.ico b/dephy-vending_machine-examples/balance-payment/app/src/app/favicon.ico new file mode 100644 index 0000000..3bc594b Binary files /dev/null and b/dephy-vending_machine-examples/balance-payment/app/src/app/favicon.ico differ diff --git a/dephy-vending_machine-examples/balance-payment/app/src/assets/react.svg b/dephy-vending_machine-examples/balance-payment/app/src/assets/react.svg new file mode 100644 index 0000000..8e0e0f1 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/assets/react.svg @@ -0,0 +1 @@ + diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-data-access.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-data-access.tsx new file mode 100644 index 0000000..d1a7678 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-data-access.tsx @@ -0,0 +1,174 @@ +import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID } from '@solana/spl-token' +import { useConnection, useWallet } from '@solana/wallet-adapter-react' +import { + Connection, + LAMPORTS_PER_SOL, + PublicKey, + SystemProgram, + TransactionMessage, + TransactionSignature, + VersionedTransaction, +} from '@solana/web3.js' +import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' +import toast from 'react-hot-toast' +import { useTransactionToast } from '../ui/ui-layout' + +export function useGetBalance({ address }: { address: PublicKey }) { + const { connection } = useConnection() + + return useQuery({ + queryKey: ['get-balance', { endpoint: connection.rpcEndpoint, address }], + queryFn: () => connection.getBalance(address), + }) +} + +export function useGetSignatures({ address }: { address: PublicKey }) { + const { connection } = useConnection() + + return useQuery({ + queryKey: ['get-signatures', { endpoint: connection.rpcEndpoint, address }], + queryFn: () => connection.getSignaturesForAddress(address), + }) +} + +export function useGetTokenAccounts({ address }: { address: PublicKey }) { + const { connection } = useConnection() + + return useQuery({ + queryKey: ['get-token-accounts', { endpoint: connection.rpcEndpoint, address }], + queryFn: async () => { + const [tokenAccounts, token2022Accounts] = await Promise.all([ + connection.getParsedTokenAccountsByOwner(address, { + programId: TOKEN_PROGRAM_ID, + }), + connection.getParsedTokenAccountsByOwner(address, { + programId: TOKEN_2022_PROGRAM_ID, + }), + ]) + return [...tokenAccounts.value, ...token2022Accounts.value] + }, + }) +} + +export function useTransferSol({ address }: { address: PublicKey }) { + const { connection } = useConnection() + const transactionToast = useTransactionToast() + const wallet = useWallet() + const client = useQueryClient() + + return useMutation({ + mutationKey: ['transfer-sol', { endpoint: connection.rpcEndpoint, address }], + mutationFn: async (input: { destination: PublicKey; amount: number }) => { + let signature: TransactionSignature = '' + try { + const { transaction, latestBlockhash } = await createTransaction({ + publicKey: address, + destination: input.destination, + amount: input.amount, + connection, + }) + + // Send transaction and await for signature + signature = await wallet.sendTransaction(transaction, connection) + + // Send transaction and await for signature + await connection.confirmTransaction({ signature, ...latestBlockhash }, 'confirmed') + + console.log(signature) + return signature + } catch (error: unknown) { + console.log('error', `Transaction failed! ${error}`, signature) + + return + } + }, + onSuccess: (signature) => { + if (signature) { + transactionToast(signature) + } + return Promise.all([ + client.invalidateQueries({ + queryKey: ['get-balance', { endpoint: connection.rpcEndpoint, address }], + }), + client.invalidateQueries({ + queryKey: ['get-signatures', { endpoint: connection.rpcEndpoint, address }], + }), + ]) + }, + onError: (error) => { + toast.error(`Transaction failed! ${error}`) + }, + }) +} + +export function useRequestAirdrop({ address }: { address: PublicKey }) { + const { connection } = useConnection() + const transactionToast = useTransactionToast() + const client = useQueryClient() + + return useMutation({ + mutationKey: ['airdrop', { endpoint: connection.rpcEndpoint, address }], + mutationFn: async (amount: number = 1) => { + const [latestBlockhash, signature] = await Promise.all([ + connection.getLatestBlockhash(), + connection.requestAirdrop(address, amount * LAMPORTS_PER_SOL), + ]) + + await connection.confirmTransaction({ signature, ...latestBlockhash }, 'confirmed') + return signature + }, + onSuccess: (signature) => { + transactionToast(signature) + return Promise.all([ + client.invalidateQueries({ + queryKey: ['get-balance', { endpoint: connection.rpcEndpoint, address }], + }), + client.invalidateQueries({ + queryKey: ['get-signatures', { endpoint: connection.rpcEndpoint, address }], + }), + ]) + }, + }) +} + +async function createTransaction({ + publicKey, + destination, + amount, + connection, +}: { + publicKey: PublicKey + destination: PublicKey + amount: number + connection: Connection +}): Promise<{ + transaction: VersionedTransaction + latestBlockhash: { blockhash: string; lastValidBlockHeight: number } +}> { + // Get the latest blockhash to use in our transaction + const latestBlockhash = await connection.getLatestBlockhash() + + // Create instructions to send, in this case a simple transfer + const instructions = [ + SystemProgram.transfer({ + fromPubkey: publicKey, + toPubkey: destination, + lamports: amount * LAMPORTS_PER_SOL, + }), + ] + + // Create a new TransactionMessage with version and compile it to legacy + const messageLegacy = new TransactionMessage({ + payerKey: publicKey, + recentBlockhash: latestBlockhash.blockhash, + instructions, + }).compileToLegacyMessage() + + // Create a new VersionedTransaction which supports legacy and v0 + const transaction = new VersionedTransaction(messageLegacy) + + return { + transaction, + latestBlockhash, + } +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-detail-feature.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-detail-feature.tsx new file mode 100644 index 0000000..0d4869e --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-detail-feature.tsx @@ -0,0 +1,44 @@ +import { PublicKey } from '@solana/web3.js' +import { useMemo } from 'react' +import { useParams } from 'react-router' +import { ExplorerLink } from '../cluster/cluster-ui' +import { AppHero, ellipsify } from '../ui/ui-layout' +import { AccountBalance, AccountButtons, AccountTokens, AccountTransactions } from './account-ui' + +export default function AccountDetailFeature() { + const params = useParams() as { address?: string } + const address = useMemo(() => { + if (!params.address) { + return + } + try { + return new PublicKey(params.address) + } catch (e) { + console.log(`Invalid public key`, e) + } + }, [params]) + if (!address) { + return
Error loading account
+ } + + return ( +
+ } + subtitle={ +
+ +
+ } + > +
+ +
+
+
+ + +
+
+ ) +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-list-feature.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-list-feature.tsx new file mode 100644 index 0000000..04d351a --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-list-feature.tsx @@ -0,0 +1,19 @@ +import { useWallet } from '@solana/wallet-adapter-react' +import { Navigate } from 'react-router' +import { WalletButton } from '../solana/solana-provider' + +export default function AccountListFeature() { + const { publicKey } = useWallet() + + if (publicKey) { + return + } + + return ( +
+
+ +
+
+ ) +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-ui.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-ui.tsx new file mode 100644 index 0000000..0c1bf09 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/account/account-ui.tsx @@ -0,0 +1,347 @@ +import { useWallet } from '@solana/wallet-adapter-react' +import { LAMPORTS_PER_SOL, PublicKey } from '@solana/web3.js' +import { IconRefresh } from '@tabler/icons-react' +import { useQueryClient } from '@tanstack/react-query' +import { useMemo, useState } from 'react' +import { useCluster } from '../cluster/cluster-data-access' +import { ExplorerLink } from '../cluster/cluster-ui' +import { AppModal, ellipsify } from '../ui/ui-layout' +import { + useGetBalance, + useGetSignatures, + useGetTokenAccounts, + useRequestAirdrop, + useTransferSol, +} from './account-data-access' + +export function AccountBalance({ address }: { address: PublicKey }) { + const query = useGetBalance({ address }) + + return ( +
+

query.refetch()}> + {query.data ? : '...'} SOL +

+
+ ) +} +export function AccountChecker() { + const { publicKey } = useWallet() + if (!publicKey) { + return null + } + return +} +export function AccountBalanceCheck({ address }: { address: PublicKey }) { + const { cluster } = useCluster() + const mutation = useRequestAirdrop({ address }) + const query = useGetBalance({ address }) + + if (query.isLoading) { + return null + } + if (query.isError || !query.data) { + return ( +
+ + You are connected to {cluster.name} but your account is not found on this cluster. + + +
+ ) + } + return null +} + +export function AccountButtons({ address }: { address: PublicKey }) { + const wallet = useWallet() + const { cluster } = useCluster() + const [showAirdropModal, setShowAirdropModal] = useState(false) + const [showReceiveModal, setShowReceiveModal] = useState(false) + const [showSendModal, setShowSendModal] = useState(false) + + return ( +
+ setShowAirdropModal(false)} address={address} show={showAirdropModal} /> + setShowReceiveModal(false)} /> + setShowSendModal(false)} /> +
+ + + +
+
+ ) +} + +export function AccountTokens({ address }: { address: PublicKey }) { + const [showAll, setShowAll] = useState(false) + const query = useGetTokenAccounts({ address }) + const client = useQueryClient() + const items = useMemo(() => { + if (showAll) return query.data + return query.data?.slice(0, 5) + }, [query.data, showAll]) + + return ( +
+
+
+

Token Accounts

+
+ {query.isLoading ? ( + + ) : ( + + )} +
+
+
+ {query.isError &&
Error: {query.error?.message.toString()}
} + {query.isSuccess && ( +
+ {query.data.length === 0 ? ( +
No token accounts found.
+ ) : ( + + + + + + + + + + {items?.map(({ account, pubkey }) => ( + + + + + + ))} + + {(query.data?.length ?? 0) > 5 && ( + + + + )} + +
Public KeyMintBalance
+
+ + + +
+
+
+ + + +
+
+ {account.data.parsed.info.tokenAmount.uiAmount} +
+ +
+ )} +
+ )} +
+ ) +} + +export function AccountTransactions({ address }: { address: PublicKey }) { + const query = useGetSignatures({ address }) + const [showAll, setShowAll] = useState(false) + + const items = useMemo(() => { + if (showAll) return query.data + return query.data?.slice(0, 5) + }, [query.data, showAll]) + + return ( +
+
+

Transaction History

+
+ {query.isLoading ? ( + + ) : ( + + )} +
+
+ {query.isError &&
Error: {query.error?.message.toString()}
} + {query.isSuccess && ( +
+ {query.data.length === 0 ? ( +
No transactions found.
+ ) : ( + + + + + + + + + + + {items?.map((item) => ( + + + + + + + ))} + {(query.data?.length ?? 0) > 5 && ( + + + + )} + +
SignatureSlotBlock TimeStatus
+ + + + {new Date((item.blockTime ?? 0) * 1000).toISOString()} + {item.err ? ( +
+ Failed +
+ ) : ( +
Success
+ )} +
+ +
+ )} +
+ )} +
+ ) +} + +function BalanceSol({ balance }: { balance: number }) { + return {Math.round((balance / LAMPORTS_PER_SOL) * 100000) / 100000} +} + +function ModalReceive({ hide, show, address }: { hide: () => void; show: boolean; address: PublicKey }) { + return ( + +

Receive assets by sending them to your public key:

+ {address.toString()} +
+ ) +} + +function ModalAirdrop({ hide, show, address }: { hide: () => void; show: boolean; address: PublicKey }) { + const mutation = useRequestAirdrop({ address }) + const [amount, setAmount] = useState('2') + + return ( + mutation.mutateAsync(parseFloat(amount)).then(() => hide())} + > + setAmount(e.target.value)} + /> + + ) +} + +function ModalSend({ hide, show, address }: { hide: () => void; show: boolean; address: PublicKey }) { + const wallet = useWallet() + const mutation = useTransferSol({ address }) + const [destination, setDestination] = useState('') + const [amount, setAmount] = useState('1') + + if (!address || !wallet.sendTransaction) { + return
Wallet not connected
+ } + + return ( + { + mutation + .mutateAsync({ + destination: new PublicKey(destination), + amount: parseFloat(amount), + }) + .then(() => hide()) + }} + > + setDestination(e.target.value)} + /> + setAmount(e.target.value)} + /> + + ) +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/balance-payment/balance-payment-data-access.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/balance-payment/balance-payment-data-access.tsx new file mode 100644 index 0000000..8013e85 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/balance-payment/balance-payment-data-access.tsx @@ -0,0 +1,72 @@ +import { getBalancePaymentProgram, getBalancePaymentProgramId } from '../../anchor' +import { Cluster } from '@solana/web3.js' +import { v4 as uuidv4 } from "uuid"; +import { useMemo } from 'react' +import { useCluster } from '../cluster/cluster-data-access' +import { useAnchorProvider } from '../solana/solana-provider' +import { BN, web3 } from '@coral-xyz/anchor' + +export function useBalancePaymentProgram() { + const { cluster } = useCluster() + const provider = useAnchorProvider() + const programId = useMemo(() => getBalancePaymentProgramId(cluster.network as Cluster), [cluster]) + const program = useMemo(() => getBalancePaymentProgram(provider, programId), [provider, programId]) + + const getGlobalPubkey = () => { + const [globalAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("GLOBAL")], + programId + ); + return globalAccountPubkey; + } + + const getUserAccountPubkey = (user: web3.PublicKey) => { + const [userAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("USER"), user.toBuffer()], + programId + ); + return userAccountPubkey; + }; + + const getUserVaultPubkey = (user: web3.PublicKey) => { + const [vaultPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("VAULT"), user.toBuffer()], + programId + ); + return vaultPubkey; + }; + + const getLockAccountPubkey = (user: web3.PublicKey, nonce: BN) => { + const [lockAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [ + Buffer.from("LOCK"), + user.toBuffer(), + nonce.toArrayLike(Buffer, "le", 8), + ], + program.programId + ); + return lockAccountPubkey; + }; + + const generate64ByteUUIDPayload = () => { + const uuid = uuidv4().replace(/-/g, ""); // 去掉连字符 + const uuidBuffer = Buffer.from(uuid, "hex"); + + const extendedBuffer = Buffer.concat([uuidBuffer, Buffer.alloc(48, 0)]); + + return { + uuid, + uuidBytes: extendedBuffer + }; + }; + + return { + program, + programId, + getGlobalPubkey, + getUserAccountPubkey, + getUserVaultPubkey, + getLockAccountPubkey, + generate64ByteUUIDPayload + } +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/balance-payment/balance-payment-feature.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/balance-payment/balance-payment-feature.tsx new file mode 100644 index 0000000..c68f338 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/balance-payment/balance-payment-feature.tsx @@ -0,0 +1,721 @@ +import { useWallet } from '@solana/wallet-adapter-react' +import { WalletButton } from '../solana/solana-provider' +import { useBalancePaymentProgram } from './balance-payment-data-access' +import { useEffect, useState, useRef } from 'react' +import { BN } from '@coral-xyz/anchor' +import keccak from 'keccak' +import { useTransactionToast } from '../ui/ui-layout' +import toast from 'react-hot-toast' +import { finalizeEvent, generateSecretKey } from 'nostr-tools/pure' +import { Relay } from 'nostr-tools/relay' +import bs58 from 'bs58' + +const SIGN_MESSAGE_PREFIX = 'DePHY vending machine/Example:\n' +const RELAY_ENDPOINT = import.meta.env.VITE_RELAY_ENDPOINT || 'ws://127.0.0.1:8000' + +// define charge status +type ChargeStatus = 'idle' | 'requested' | 'working' | 'available' | 'error' + +export default function BalancePaymentFeature() { + const transactionToast = useTransactionToast() + const { publicKey, wallet, signMessage } = useWallet() + const { program, getGlobalPubkey, getUserAccountPubkey, generate64ByteUUIDPayload } = useBalancePaymentProgram() + + const [selectedTab, setSelectedTab] = useState<'decharge' | 'gacha'>('decharge') + const [recoverInfo, setRecoverInfo] = useState() + const [serialNumberStr, setSerialNumberStr] = useState(null) + const [serialNumberBytes, setSerialNumberBytes] = useState(null) + const [globalAccount, setGlobalAccount] = useState(null) + const [userAccount, setUserAccount] = useState(null) + const [vaultBalance, setVaultBalance] = useState(null) + const [depositAmount, setDepositAmount] = useState('') + const [withdrawAmount, setWithdrawAmount] = useState('') + const [machinePubkey, setMachinePubkey] = useState( + 'd041ea9854f2117b82452457c4e6d6593a96524027cd4032d2f40046deb78d93', + ) + const [relay, setRelay] = useState() + const [sk, setSk] = useState(null) + const [chargeStatus, setChargeStatus] = useState('idle') + const [events, setEvents] = useState([]) + const [expandedEventIndex, setExpandedEventIndex] = useState(null) + const [isChargeDisabled, setIsChargeDisabled] = useState(false) + const isTabDisabled = chargeStatus !== 'idle' && chargeStatus !== 'available' + const [initialRequestId, setInitialRequestId] = useState(null) + const [initialPayload, setInitialPayload] = useState(null) + const [stopFlag, setStopFlag] = useState(false) + const [isStopPending, setIsStopPending] = useState(false) + + const subscriptionRef = useRef(null) + + useEffect(() => { + const { uuid, uuidBytes } = generate64ByteUUIDPayload() + setSerialNumberStr(uuid) + setSerialNumberBytes(uuidBytes) + }, [selectedTab]) + + useEffect(() => { + if (!globalAccount) { + fetchGlobalAccount() + } + }, [program]) + + useEffect(() => { + if (!userAccount) { + fetchUserAccount() + } + }, [program, publicKey]) + + useEffect(() => { + if (publicKey) { + const intervalId = setInterval(fetchUserAccount, 3000) + + return () => clearInterval(intervalId) + } + }, [publicKey]) + + useEffect(() => { + ;(async () => { + const sk = generateSecretKey() + setSk(sk) + + try { + const relay = await Relay.connect(RELAY_ENDPOINT) + setRelay(relay) + toast.success(`connected to ${relay.url}`) + } catch (error) { + toast.error(`fail to connect relay, ${error}`) + } + })() + }, []) + + const solToLamports = (sol: string): BN => { + const solNumber = parseFloat(sol) + if (isNaN(solNumber) || solNumber < 0) { + throw new Error('Invalid SOL amount') + } + return new BN(solNumber * 10 ** 9) + } + + const handleRegister = async () => { + if (!publicKey || !program) { + console.error('Wallet not connected or program not loaded') + return + } + + try { + const transactionSignature = await program.methods + .register() + .accountsPartial({ + user: publicKey, + }) + .rpc() + + console.log('Register transaction signature:', transactionSignature) + transactionToast(transactionSignature) + + const userAccountPubkey = getUserAccountPubkey(publicKey) + const user = await program.account.userAccount.fetch(userAccountPubkey) + setUserAccount(user) + const userVaultBalance = await program.provider.connection.getBalance(user.vault) + setVaultBalance(userVaultBalance) + } catch (error) { + toast.error(`Error registering user account: ${error}`) + } + } + + const handleDeposit = async () => { + if (!publicKey || !program || !depositAmount) { + console.error('Wallet not connected or program not loaded or amount not set') + return + } + + try { + const amount = solToLamports(depositAmount) + const transactionSignature = await program.methods + .deposit(amount) + .accountsPartial({ + user: publicKey, + }) + .rpc() + + console.log('Deposit transaction signature:', transactionSignature) + transactionToast(transactionSignature) + + const userAccountPubkey = getUserAccountPubkey(publicKey) + const user = await program.account.userAccount.fetch(userAccountPubkey) + const userVaultBalance = await program.provider.connection.getBalance(user.vault) + setVaultBalance(userVaultBalance) + } catch (error) { + toast.error(`Error depositing: ${error}`) + } + } + + const handleWithdraw = async () => { + if (!publicKey || !program || !withdrawAmount) { + console.error('Wallet not connected or program not loaded or amount not set') + return + } + + try { + const amount = solToLamports(withdrawAmount) + const transactionSignature = await program.methods + .withdraw(amount) + .accountsPartial({ + user: publicKey, + }) + .rpc() + + console.log('Withdraw transaction signature:', transactionSignature) + transactionToast(transactionSignature) + + const userAccountPubkey = getUserAccountPubkey(publicKey) + const user = await program.account.userAccount.fetch(userAccountPubkey) + const userVaultBalance = await program.provider.connection.getBalance(user.vault) + setVaultBalance(userVaultBalance) + } catch (error) { + toast.error(`Error withdrawing: ${error}`) + } + } + + const handleSelectTab = (tab: 'decharge' | 'gacha') => { + if (isTabDisabled) { + return + } + setSelectedTab(tab) + handleReset() + } + + const fetchGlobalAccount = async () => { + if (!program) return + + const globalAccountPubkey = getGlobalPubkey() + const global = await program.account.globalAccount.fetch(globalAccountPubkey) + setGlobalAccount(global) + } + + const fetchUserAccount = async () => { + if (!publicKey || !program) return + + const userAccountPubkey = getUserAccountPubkey(publicKey) + console.log('userAccountPubkey:', userAccountPubkey.toString()) + const user = await program.account.userAccount.fetch(userAccountPubkey) + const userVaultBalance = await program.provider.connection.getBalance(user.vault) + setVaultBalance(userVaultBalance) + setUserAccount(user) + } + + const handleCharge = async () => { + if (!wallet || !publicKey || !signMessage || !serialNumberBytes) { + console.error('Wallet not connected or serial number not generated') + return + } + + setIsChargeDisabled(true) + + const userAccountPubkey = getUserAccountPubkey(publicKey) + const user = await program.account.userAccount.fetch(userAccountPubkey) + + const nonce = user.nonce + const payload = serialNumberBytes + const deadline = new BN(Date.now() / 1000 + 60 * 30) // 30 minutes later + + const message = Buffer.concat([payload, nonce.toArrayLike(Buffer, 'le', 8), deadline.toArrayLike(Buffer, 'le', 8)]) + const messageHash = keccak('keccak256').update(message).digest() + const hashedMessageBase58 = bs58.encode(messageHash) + const digest = new TextEncoder().encode(`${SIGN_MESSAGE_PREFIX}${hashedMessageBase58}`) + + let recoverInfo + try { + const signature = await signMessage(digest) + recoverInfo = { + signature: Array.from(signature), + payload: Array.from(payload), + deadline: deadline.toNumber(), + } + setRecoverInfo(recoverInfo) + } catch (error) { + toast.error(`Error signing message: ${error}`) + setIsChargeDisabled(false) + return + } + + try { + await publishToRelay(nonce.toNumber(), recoverInfo, publicKey.toString()) + } catch (error) { + toast.error(`Error publishing to relay: ${error}`) + setIsChargeDisabled(false) + return + } + + try { + await listenFromRelay() + } catch (error) { + toast.error(`Error listening from relay: ${error}`) + setIsChargeDisabled(false) + } + } + + const handleStop = async () => { + if (!sk || !relay || !machinePubkey || !initialRequestId || !initialPayload) { + toast.error('Not initialized') + return + } + + setIsStopPending(true) + try { + const sTag = selectedTab === 'decharge' ? 'dephy-decharge-controller' : 'dephy-gacha-controller' + const contentData = { + Request: { + to_status: 'Available', + reason: 'UserRequest', + initial_request: initialRequestId, + payload: initialPayload, + }, + } + + const content = JSON.stringify(contentData) + const eventTemplate = { + kind: 1573, + created_at: Math.floor(Date.now() / 1000), + tags: [ + ['s', sTag], + ['p', machinePubkey], + ], + content, + } + const signedEvent = finalizeEvent(eventTemplate, sk) + await relay.publish(signedEvent) + toast.success(`Stop request id [${initialRequestId}]`) + setStopFlag(true) + } catch (error) { + toast.error(`Failed to send stop request: ${error}`) + setIsStopPending(false) + } + } + + const publishToRelay = async (nonce: number, recoverInfo: any, user: string) => { + if (!sk) { + toast.error('sk not initialized') + return + } + if (!machinePubkey) { + toast.error('machinePubkey not initialized') + return + } + if (!relay) { + toast.error('relay not initialized') + return + } + const sTag = selectedTab === 'decharge' ? 'dephy-decharge-controller' : 'dephy-gacha-controller' + + const payload = JSON.stringify({ + recover_info: JSON.stringify(recoverInfo), + nonce, + user, + }) + + setInitialPayload(payload) + + const contentData = { + Request: { + to_status: 'Working', + reason: 'UserRequest', + initial_request: '0000000000000000000000000000000000000000000000000000000000000000', + payload, + }, + } + + const content = JSON.stringify(contentData) + + let eventTemplate = { + kind: 1573, + created_at: Math.floor(Date.now() / 1000), + tags: [ + ['s', sTag], + ['p', machinePubkey], + ], + content, + } + const signedEvent = finalizeEvent(eventTemplate, sk) + await relay.publish(signedEvent) + } + + const listenFromRelay = async () => { + if (!sk) { + toast.error('sk not initialized') + return + } + if (!machinePubkey) { + toast.error('machinePubkey not initialized') + return + } + if (!relay) { + toast.error('relay not initialized') + return + } + + const sTag = selectedTab === 'decharge' ? 'dephy-decharge-controller' : 'dephy-gacha-controller' + + // clear old subscription + if (subscriptionRef.current) { + subscriptionRef.current.close() + } + + // create new subscription + subscriptionRef.current = relay.subscribe( + [ + { + kinds: [1573], + since: Math.floor(Date.now() / 1000), + '#s': [sTag], + '#p': [machinePubkey], + }, + ], + { + onevent: async (event) => { + console.log('event received:', event) + try { + const content = JSON.parse(event.content) + if (content.Request) { + setChargeStatus('requested') + setInitialRequestId(event.id) + } else if (content.Status) { + if (content.Status.status === 'Working') { + setChargeStatus('working') + } else if (content.Status.status === 'Available') { + setChargeStatus('available') + setIsChargeDisabled(false) + } + } + setEvents((prevEvents) => [...prevEvents, event]) + } catch (error) { + console.error('Error parsing event content:', error) + setChargeStatus('error') + setEvents((prevEvents) => [...prevEvents, { error: 'Failed to parse event content', rawEvent: event }]) + } + }, + oneose() { + console.log('eose received') + }, + onclose(reason) { + console.log('close received:', reason) + }, + }, + ) + } + + // reset status + const handleReset = () => { + // clear old subscription + if (subscriptionRef.current) { + subscriptionRef.current.close() + subscriptionRef.current = null + } + + setRecoverInfo(null) + setEvents([]) + setChargeStatus('idle') + setIsChargeDisabled(false) + setInitialRequestId(null) + setInitialPayload(null) + setStopFlag(false) + setIsStopPending(false) + } + + const ProgressBar = () => { + let progress = 0 + // let statusText = '' + let barColor = 'bg-gray-300' // default gray + + const statusTextMap = { + decharge: { + requested: 'Requested - Waiting for charging station...', + working: 'Working - Charging in progress...', + available: `Available - Charging ${stopFlag ? 'stopped' : 'completed'}!`, + error: 'Error - Charging failed!', + idle: 'Idle - Ready to charge', + }, + gacha: { + requested: 'Requested - Waiting for gacha machine...', + working: 'Working - Gacha in progress...', + available: 'Available - Gacha completed!', + error: 'Error - Gacha failed!', + idle: 'Idle - Ready to play', + }, + } + + const statusText = statusTextMap[selectedTab][chargeStatus] + + switch (chargeStatus) { + case 'requested': + progress = 33 + // statusText = 'Requested - Waiting for charging station...' + barColor = 'bg-blue-500' + break + case 'working': + progress = 66 + // statusText = 'Working - Charging in progress...' + barColor = 'bg-blue-500' + break + case 'available': + progress = 100 + // statusText = 'Available - Charging completed!' + barColor = 'bg-green-500' + break + case 'error': + progress = 100 + // statusText = 'Error - Something went wrong!' + barColor = 'bg-red-500' + break + default: + progress = 0 + // statusText = 'Idle - Ready to charge' + barColor = 'bg-gray-300' + } + + return ( +
+
+
+
+

{statusText}

+
+ ) + } + + const EventJsonViewer = ({ event, index }: { event: any; index: number }) => { + const isExpanded = expandedEventIndex === index + + const toggleExpand = () => { + if (isExpanded) { + setExpandedEventIndex(null) + } else { + setExpandedEventIndex(index) + } + } + + const getPurpose = () => { + const sTag = event.tags.find((t: string[]) => t[0] === 's')?.[1] + const eventType = sTag === 'dephy-decharge-controller' ? 'Decharge' : 'Gacha' + + try { + const content = JSON.parse(event.content) + if (content.Request) return `${eventType} Request` + if (content.Status) return `${eventType} Status: ${content.Status.status}` + } catch { + return 'Invalid Event' + } + return 'Unknown Event' + } + + const formatTime = (timestamp: number) => { + return new Date(timestamp * 1000).toLocaleString() + } + + return ( +
+
+ + {isExpanded ? '▲' : '▼'} + Event {index + 1} - {getPurpose()} + +
+ {formatTime(event.created_at)} +
+
+ {isExpanded && ( +
{JSON.stringify(event, null, 2)}
+ )} +
+ ) + } + + return publicKey ? ( +
+ {/* Tab */} +
+ + +
+ +
+ {/* userAccount */} +
+

User Account

+ {userAccount ? ( +
+

+ Nonce: {userAccount.nonce.toString()} +

+

+ Locked Amount:{' '} + {userAccount.lockedAmount.toNumber() / 10 ** 9} SOL +

+

+ Vault: {userAccount.vault.toString()} +

+

+ Vault Balance:{' '} + {vaultBalance ? `${vaultBalance / 10 ** 9} SOL` : 'Loading...'} +

+
+ ) : ( +
+

No user account data found.

+ +
+ )} +
+ + {/* deposit */} +
+

Deposit

+
+ setDepositAmount(e.target.value)} + className="input input-bordered w-full placeholder:text-sm" + /> + +
+
+ + {/* withdraw */} +
+

Withdraw

+
+ setWithdrawAmount(e.target.value)} + className="input input-bordered w-full placeholder:text-sm" + /> + +
+
+
+ +
+

{selectedTab === 'decharge' ? 'Charge' : 'Gacha'}

+ + + {events.map((event, index) => ( + + ))} + + {/* reset */} + {chargeStatus === 'available' && ( + + )} + + {serialNumberBytes && ( +
+

Charger Serial Number

+

{serialNumberStr}

+
+ )} + +
+

Machine Pubkey

+ setMachinePubkey(e.target.value)} + className="input input-bordered w-full placeholder:text-sm mt-4" + /> +
+ + {/* charge */} + + + {/* stop */} + {selectedTab === 'decharge' && ( + + )} + + {recoverInfo && ( +
+

Recover Info

+
+

+ Signature:{' '} + {recoverInfo.signature.join(', ')} +

+

+ Payload:{' '} + {recoverInfo.payload.join(', ')} +

+

+ Deadline: {recoverInfo.deadline.toString()} +

+
+
+ )} +
+
+ ) : ( +
+
+
+ +
+
+
+ ) +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/cluster/cluster-data-access.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/cluster/cluster-data-access.tsx new file mode 100644 index 0000000..2da2f4a --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/cluster/cluster-data-access.tsx @@ -0,0 +1,118 @@ +import { clusterApiUrl, Connection } from '@solana/web3.js' + +import { atom, useAtomValue, useSetAtom } from 'jotai' +import { atomWithStorage } from 'jotai/utils' +import { createContext, ReactNode, useContext } from 'react' +import toast from 'react-hot-toast' + +export interface Cluster { + name: string + endpoint: string + network?: ClusterNetwork + active?: boolean +} + +export enum ClusterNetwork { + Mainnet = 'mainnet-beta', + Testnet = 'testnet', + Devnet = 'devnet', + Custom = 'custom', +} + +// By default, we don't configure the mainnet-beta cluster +// The endpoint provided by clusterApiUrl('mainnet-beta') does not allow access from the browser due to CORS restrictions +// To use the mainnet-beta cluster, provide a custom endpoint +export const defaultClusters: Cluster[] = [ + { + name: 'devnet', + endpoint: clusterApiUrl('devnet'), + network: ClusterNetwork.Devnet, + }, + { name: 'local', endpoint: 'http://localhost:8899' }, + { + name: 'testnet', + endpoint: clusterApiUrl('testnet'), + network: ClusterNetwork.Testnet, + }, +] + +const index = import.meta.env.VITE_NETWORK === "devnet" ? 0 : 1; // default is local if `VITE_NETWORK` env not provided + +const clusterAtom = atomWithStorage('solana-cluster', defaultClusters[index]) +const clustersAtom = atomWithStorage('solana-clusters', defaultClusters) + +const activeClustersAtom = atom((get) => { + const clusters = get(clustersAtom) + const cluster = get(clusterAtom) + return clusters.map((item) => ({ + ...item, + active: item.name === cluster.name, + })) +}) + +const activeClusterAtom = atom((get) => { + const clusters = get(activeClustersAtom) + + return clusters.find((item) => item.active) || clusters[0] +}) + +export interface ClusterProviderContext { + cluster: Cluster + clusters: Cluster[] + addCluster: (cluster: Cluster) => void + deleteCluster: (cluster: Cluster) => void + setCluster: (cluster: Cluster) => void + getExplorerUrl(path: string): string +} + +const Context = createContext({} as ClusterProviderContext) + +export function ClusterProvider({ children }: { children: ReactNode }) { + const cluster = useAtomValue(activeClusterAtom) + const clusters = useAtomValue(activeClustersAtom) + const setCluster = useSetAtom(clusterAtom) + const setClusters = useSetAtom(clustersAtom) + + const value: ClusterProviderContext = { + cluster, + clusters: clusters.sort((a, b) => (a.name > b.name ? 1 : -1)), + addCluster: (cluster: Cluster) => { + try { + new Connection(cluster.endpoint) + setClusters([...clusters, cluster]) + } catch (err) { + toast.error(`${err}`) + } + }, + deleteCluster: (cluster: Cluster) => { + setClusters(clusters.filter((item) => item.name !== cluster.name)) + }, + setCluster: (cluster: Cluster) => setCluster(cluster), + getExplorerUrl: (path: string) => `https://explorer.solana.com/${path}${getClusterUrlParam(cluster)}`, + } + return {children} +} + +export function useCluster() { + return useContext(Context) +} + +function getClusterUrlParam(cluster: Cluster): string { + let suffix = '' + switch (cluster.network) { + case ClusterNetwork.Devnet: + suffix = 'devnet' + break + case ClusterNetwork.Mainnet: + suffix = '' + break + case ClusterNetwork.Testnet: + suffix = 'testnet' + break + default: + suffix = `custom&customUrl=${encodeURIComponent(cluster.endpoint)}` + break + } + + return suffix.length ? `?cluster=${suffix}` : '' +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/cluster/cluster-feature.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/cluster/cluster-feature.tsx new file mode 100644 index 0000000..e7608aa --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/cluster/cluster-feature.tsx @@ -0,0 +1,19 @@ +import { useState } from 'react' +import { AppHero } from '../ui/ui-layout' +import { ClusterUiModal, ClusterUiTable } from './cluster-ui' + +export default function ClusterFeature() { + const [showModal, setShowModal] = useState(false) + + return ( +
+ + setShowModal(false)} /> + + + +
+ ) +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/cluster/cluster-ui.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/cluster/cluster-ui.tsx new file mode 100644 index 0000000..ce62148 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/cluster/cluster-ui.tsx @@ -0,0 +1,172 @@ +import { useConnection } from '@solana/wallet-adapter-react' +import { Connection } from '@solana/web3.js' +import { IconTrash } from '@tabler/icons-react' +import { useQuery } from '@tanstack/react-query' +import { ReactNode, useState } from 'react' +import { AppModal } from '../ui/ui-layout' +import { ClusterNetwork, useCluster } from './cluster-data-access' + +export function ExplorerLink({ path, label, className }: { path: string; label: string; className?: string }) { + const { getExplorerUrl } = useCluster() + return ( + + {label} + + ) +} + +export function ClusterChecker({ children }: { children: ReactNode }) { + const { cluster } = useCluster() + const { connection } = useConnection() + + const query = useQuery({ + queryKey: ['version', { cluster, endpoint: connection.rpcEndpoint }], + queryFn: () => connection.getVersion(), + retry: 1, + }) + if (query.isLoading) { + return null + } + if (query.isError || !query.data) { + return ( +
+ + Error connecting to cluster {cluster.name} + + +
+ ) + } + return children +} + +export function ClusterUiSelect() { + const { clusters, setCluster, cluster } = useCluster() + return ( +
+ +
    + {clusters.map((item) => ( +
  • + +
  • + ))} +
+
+ ) +} + +export function ClusterUiModal({ hideModal, show }: { hideModal: () => void; show: boolean }) { + const { addCluster } = useCluster() + const [name, setName] = useState('') + const [network, setNetwork] = useState() + const [endpoint, setEndpoint] = useState('') + + return ( + { + try { + new Connection(endpoint) + if (name) { + addCluster({ name, network, endpoint }) + hideModal() + } else { + console.log('Invalid cluster name') + } + } catch { + console.log('Invalid cluster endpoint') + } + }} + submitLabel="Save" + > + setName(e.target.value)} + /> + setEndpoint(e.target.value)} + /> + + + ) +} + +export function ClusterUiTable() { + const { clusters, setCluster, deleteCluster } = useCluster() + return ( +
+ + + + + + + + + {clusters.map((item) => ( + + + + + ))} + +
Name/ Network / EndpointActions
+
+ + {item?.active ? ( + item.name + ) : ( + + )} + +
+ Network: {item.network ?? 'custom'} +
{item.endpoint}
+
+ +
+
+ ) +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/dashboard/dashboard-feature.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/dashboard/dashboard-feature.tsx new file mode 100644 index 0000000..50b2730 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/dashboard/dashboard-feature.tsx @@ -0,0 +1,29 @@ +import { AppHero } from '../ui/ui-layout' + +const links: { label: string; href: string }[] = [ + { label: 'Solana Docs', href: 'https://docs.solana.com/' }, + { label: 'Solana Faucet', href: 'https://faucet.solana.com/' }, + { label: 'Solana Cookbook', href: 'https://solanacookbook.com/' }, + { label: 'Solana Stack Overflow', href: 'https://solana.stackexchange.com/' }, + { label: 'Solana Developers GitHub', href: 'https://github.com/solana-developers/' }, +] + +export default function DashboardFeature() { + return ( +
+ +
+
+

Here are some helpful links to get you started.

+ {links.map((link, index) => ( + + ))} +
+
+
+ ) +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/solana/solana-provider.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/solana/solana-provider.tsx new file mode 100644 index 0000000..b7b316e --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/solana/solana-provider.tsx @@ -0,0 +1,39 @@ +import { AnchorProvider } from '@coral-xyz/anchor' +import { WalletError } from '@solana/wallet-adapter-base' +import { + AnchorWallet, + ConnectionProvider, + useConnection, + useWallet, + WalletProvider, +} from '@solana/wallet-adapter-react' +import { WalletModalProvider, WalletMultiButton } from '@solana/wallet-adapter-react-ui' +import { ReactNode, useCallback, useMemo } from 'react' +import { useCluster } from '../cluster/cluster-data-access' + +import('@solana/wallet-adapter-react-ui/styles.css') + +export const WalletButton = WalletMultiButton + +export function SolanaProvider({ children }: { children: ReactNode }) { + const { cluster } = useCluster() + const endpoint = useMemo(() => cluster.endpoint, [cluster]) + const onError = useCallback((error: WalletError) => { + console.error(error) + }, []) + + return ( + + + {children} + + + ) +} + +export function useAnchorProvider() { + const { connection } = useConnection() + const wallet = useWallet() + + return new AnchorProvider(connection, wallet as AnchorWallet, { commitment: 'confirmed' }) +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/components/ui/ui-layout.tsx b/dephy-vending_machine-examples/balance-payment/app/src/components/ui/ui-layout.tsx new file mode 100644 index 0000000..55df50f --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/components/ui/ui-layout.tsx @@ -0,0 +1,156 @@ +import { ReactNode, Suspense, useEffect, useRef } from 'react' +import toast, { Toaster } from 'react-hot-toast' +import { Link, useLocation } from 'react-router-dom' + +import { AccountChecker } from '../account/account-ui' +import { ClusterChecker, ClusterUiSelect, ExplorerLink } from '../cluster/cluster-ui' +import { WalletButton } from '../solana/solana-provider' + +export function UiLayout({ children, links }: { children: ReactNode; links: { label: string; path: string }[] }) { + const pathname = useLocation().pathname + + return ( +
+
+
+ + Payment + +
    + {links.map(({ label, path }) => ( +
  • + + {label} + +
  • + ))} +
+
+
+ + +
+
+ + + +
+ + +
+ } + > + {children} + + +
+ + + ) +} + +export function AppModal({ + children, + title, + hide, + show, + submit, + submitDisabled, + submitLabel, +}: { + children: ReactNode + title: string + hide: () => void + show: boolean + submit?: () => void + submitDisabled?: boolean + submitLabel?: string +}) { + const dialogRef = useRef(null) + + useEffect(() => { + if (!dialogRef.current) return + if (show) { + dialogRef.current.showModal() + } else { + dialogRef.current.close() + } + }, [show, dialogRef]) + + return ( + +
+

{title}

+ {children} +
+
+ {submit ? ( + + ) : null} + +
+
+
+
+ ) +} + +export function AppHero({ + children, + title, + subtitle, +}: { + children?: ReactNode + title: ReactNode + subtitle: ReactNode +}) { + return ( +
+
+
+ {typeof title === 'string' ?

{title}

: title} + {typeof subtitle === 'string' ?

{subtitle}

: subtitle} + {children} +
+
+
+ ) +} + +export function ellipsify(str = '', len = 4) { + if (str.length > 30) { + return str.substring(0, len) + '..' + str.substring(str.length - len, str.length) + } + return str +} + +export function useTransactionToast() { + return (signature: string) => { + toast.success( +
+
Transaction sent
+ +
, + ) + } +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/index.css b/dephy-vending_machine-examples/balance-payment/app/src/index.css new file mode 100644 index 0000000..3ddb6b1 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/index.css @@ -0,0 +1,20 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +html, +body, +#root { + height: 100%; +} + +.wallet-adapter-button-trigger { + background: rgb(100, 26, 230) !important; + border-radius: 8px !important; + padding-left: 16px !important; + padding-right: 16px !important; +} +.wallet-adapter-dropdown-list, +.wallet-adapter-button { + font-family: inherit !important; +} diff --git a/dephy-vending_machine-examples/balance-payment/app/src/main.tsx b/dephy-vending_machine-examples/balance-payment/app/src/main.tsx new file mode 100644 index 0000000..7fc7e3c --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/main.tsx @@ -0,0 +1,13 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import { BrowserRouter } from 'react-router-dom' +import { App } from './app/app.tsx' +import './index.css' + +createRoot(document.getElementById('root')!).render( + + + + + , +) diff --git a/dephy-vending_machine-examples/balance-payment/app/src/vite-env.d.ts b/dephy-vending_machine-examples/balance-payment/app/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/dephy-vending_machine-examples/balance-payment/app/tailwind.config.ts b/dephy-vending_machine-examples/balance-payment/app/tailwind.config.ts new file mode 100644 index 0000000..1ff77a0 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/tailwind.config.ts @@ -0,0 +1,14 @@ +import type { Config } from 'tailwindcss' + +const config: Config = { + content: [ + './src/pages/**/*.{js,ts,jsx,tsx,mdx}', + './src/components/**/*.{js,ts,jsx,tsx,mdx}', + './src/app/**/*.{js,ts,jsx,tsx,mdx}', + ], + theme: { + extend: {}, + }, + plugins: [require('daisyui')], +} +export default config diff --git a/dephy-vending_machine-examples/balance-payment/app/tsconfig.app.json b/dephy-vending_machine-examples/balance-payment/app/tsconfig.app.json new file mode 100644 index 0000000..2a4ae51 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/tsconfig.app.json @@ -0,0 +1,28 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "paths": { + "@project/anchor": ["./anchor/src"], + "@/*": ["./src/*"] + } + }, + "include": ["src"] +} diff --git a/dephy-vending_machine-examples/balance-payment/app/tsconfig.json b/dephy-vending_machine-examples/balance-payment/app/tsconfig.json new file mode 100644 index 0000000..d32ff68 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/tsconfig.json @@ -0,0 +1,4 @@ +{ + "files": [], + "references": [{ "path": "./tsconfig.app.json" }, { "path": "./tsconfig.node.json" }] +} diff --git a/dephy-vending_machine-examples/balance-payment/app/tsconfig.node.json b/dephy-vending_machine-examples/balance-payment/app/tsconfig.node.json new file mode 100644 index 0000000..8c880e0 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/tsconfig.node.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["vite.config.ts"] +} diff --git a/dephy-vending_machine-examples/balance-payment/app/vite.config.ts b/dephy-vending_machine-examples/balance-payment/app/vite.config.ts new file mode 100644 index 0000000..84ea80d --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/app/vite.config.ts @@ -0,0 +1,34 @@ +// import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill' +import react from '@vitejs/plugin-react' +import { defineConfig } from 'vite' +import { nodePolyfills } from 'vite-plugin-node-polyfills' +import viteTsconfigPaths from 'vite-tsconfig-paths' // https://vitejs.dev/config/ + +// https://vitejs.dev/config/ +export default defineConfig({ + build: { + sourcemap: false, + rollupOptions: { + output: { + manualChunks: { + coral: ['@coral-xyz/anchor'], + jotai: ['jotai'], + react: ['react', 'react-dom'], + reactHotToast: ['react-hot-toast'], + reactRouter: ['react-router', 'react-router-dom'], + solanaWalletAdapters: [ + '@solana/wallet-adapter-base', + '@solana/wallet-adapter-react', + '@solana/wallet-adapter-react-ui', + ], + tabler: ['@tabler/icons-react'], + tanstack: ['@tanstack/react-query'], + }, + }, + }, + }, + define: { + global: 'globalThis', + }, + plugins: [viteTsconfigPaths(), react(), nodePolyfills()], +}) diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/.dockerignore b/dephy-vending_machine-examples/balance-payment/bot_example_js/.dockerignore new file mode 100644 index 0000000..98acc26 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/.dockerignore @@ -0,0 +1,11 @@ +target/ +tmp/ +log/ +Dockerfile +.dockerignore +.env +.DS_Store +.swp +.vscode +.idea +node_modules diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/Dockerfile b/dephy-vending_machine-examples/balance-payment/bot_example_js/Dockerfile new file mode 100644 index 0000000..f03beb5 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/Dockerfile @@ -0,0 +1,14 @@ +# syntax=docker/dockerfile:1 +# see all versions at https://hub.docker.com/r/oven/bun/tags +FROM oven/bun:1 + +WORKDIR /opt/balance-payment-bot +COPY . . +RUN bun install --frozen-lockfile + +# ENV SOLANA_NETWORK="devnet" +# ENV SOLANA_RPC="https://api.devnet.solana.com" + +VOLUME ["/opt/solana"] + +ENTRYPOINT ["bun", "run", "index.ts"] diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/README.md b/dephy-vending_machine-examples/balance-payment/bot_example_js/README.md new file mode 100644 index 0000000..d17a6e6 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/README.md @@ -0,0 +1,36 @@ +Bot example +==== + +## Prepare + +`bun i` + +## Sign Message + +``` +bun run index.ts sign_message --net devnet --rpc "https://api.devnet.solana.com" --keypair "./user.demo.json" --minutes 30 +``` + +## Check Eligible + +``` +bun run index.ts check_eligible --net devnet --rpc "https://api.devnet.solana.com" --user "user Solana address" --amount "0.01" --nonce "nonce from request payload" --recoverInfo "User request content(Base64)" +``` + +## Lock + +``` +bun run index.ts lock --net devnet --rpc "https://api.devnet.solana.com" --keypair "./bot.demo.json" --user "user Solana address" --amount "0.01" --recoverInfo "User request content(Base64)" +``` + +## Settle + +``` +bun run index.ts settle --net devnet --rpc "https://api.devnet.solana.com" --keypair "./bot.demo.json" --user "user Solana address" --nonce "nonce related lock" --amountToTransfer "0.005" +``` + +## Build Docker image + +``` +docker build --platform linux/amd64,linux/arm64 -t balance-payment-bot . +``` diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/balance_payment.json b/dephy-vending_machine-examples/balance-payment/bot_example_js/balance_payment.json new file mode 100644 index 0000000..ea09320 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/balance_payment.json @@ -0,0 +1,932 @@ +{ + "address": "GguVKxU88NUe3GLtns7Uaa6a8Pjb9USKq3WD1rjZnPS9", + "metadata": { + "name": "balance_payment", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "deposit", + "discriminator": [ + 242, + 35, + 198, + 137, + 82, + 225, + 242, + 182 + ], + "accounts": [ + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true, + "signer": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "global_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority" + }, + { + "name": "treasury" + }, + { + "name": "bot" + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "lock", + "discriminator": [ + 21, + 19, + 208, + 43, + 237, + 62, + 255, + 87 + ], + "accounts": [ + { + "name": "global_account", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "lock_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 76, + 79, + 67, + 75 + ] + }, + { + "kind": "account", + "path": "user" + }, + { + "kind": "account", + "path": "user_account.nonce", + "account": "UserAccount" + } + ] + } + }, + { + "name": "vault", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "global_account" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "recover_info", + "type": { + "defined": { + "name": "ED25519RecoverInfo" + } + } + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "pay", + "discriminator": [ + 119, + 18, + 216, + 65, + 192, + 117, + 122, + 220 + ], + "accounts": [ + { + "name": "global_account", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "global_account" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "recover_info", + "type": { + "defined": { + "name": "ED25519RecoverInfo" + } + } + }, + { + "name": "amount_to_transfer", + "type": "u64" + } + ] + }, + { + "name": "register", + "discriminator": [ + 211, + 124, + 67, + 15, + 211, + 194, + 178, + 240 + ], + "accounts": [ + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "signer": true + }, + { + "name": "vault", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "set_bot", + "discriminator": [ + 136, + 185, + 99, + 236, + 200, + 131, + 204, + 118 + ], + "accounts": [ + { + "name": "global_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority", + "signer": true, + "relations": [ + "global_account" + ] + }, + { + "name": "bot" + }, + { + "name": "payer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "set_treasury", + "discriminator": [ + 57, + 97, + 196, + 95, + 195, + 206, + 106, + 136 + ], + "accounts": [ + { + "name": "global_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority", + "signer": true, + "relations": [ + "global_account" + ] + }, + { + "name": "treasury" + }, + { + "name": "payer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "settle", + "discriminator": [ + 175, + 42, + 185, + 87, + 144, + 131, + 102, + 212 + ], + "accounts": [ + { + "name": "global_account", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "lock_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 76, + 79, + 67, + 75 + ] + }, + { + "kind": "account", + "path": "user" + }, + { + "kind": "arg", + "path": "nonce" + } + ] + } + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "global_account" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "_nonce", + "type": "u64" + }, + { + "name": "amount_to_transfer", + "type": "u64" + } + ] + }, + { + "name": "withdraw", + "discriminator": [ + 183, + 18, + 70, + 156, + 148, + 109, + 161, + 34 + ], + "accounts": [ + { + "name": "user_account", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true, + "signer": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "system_program", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "GlobalAccount", + "discriminator": [ + 129, + 105, + 124, + 171, + 189, + 42, + 108, + 69 + ] + }, + { + "name": "LockAccount", + "discriminator": [ + 223, + 64, + 71, + 124, + 255, + 86, + 118, + 192 + ] + }, + { + "name": "UserAccount", + "discriminator": [ + 211, + 33, + 136, + 16, + 186, + 110, + 242, + 127 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "Unauthorized", + "msg": "Unauthorized access." + }, + { + "code": 6001, + "name": "InsufficientFunds", + "msg": "Insufficient funds." + }, + { + "code": 6002, + "name": "SignatureFormatInvalid", + "msg": "The signature format or recovery ID is incorrect." + }, + { + "code": 6003, + "name": "SignatureRecoveryFailed", + "msg": "Failed to recover public key from signature." + }, + { + "code": 6004, + "name": "SignatureMismatch", + "msg": "The recovered public key does not match the user's public key." + }, + { + "code": 6005, + "name": "SignatureExpired", + "msg": "The signature is expired." + } + ], + "types": [ + { + "name": "ED25519RecoverInfo", + "type": { + "kind": "struct", + "fields": [ + { + "name": "signature", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "payload", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "deadline", + "type": "i64" + } + ] + } + }, + { + "name": "GlobalAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "bot", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + } + ] + } + }, + { + "name": "LockAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + } + ] + } + }, + { + "name": "UserAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "nonce", + "type": "u64" + }, + { + "name": "locked_amount", + "type": "u64" + }, + { + "name": "vault", + "type": "pubkey" + } + ] + } + } + ] +} diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/balance_payment.ts b/dephy-vending_machine-examples/balance-payment/bot_example_js/balance_payment.ts new file mode 100644 index 0000000..ecda99e --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/balance_payment.ts @@ -0,0 +1,938 @@ +/** + * Program IDL in camelCase format in order to be used in JS/TS. + * + * Note that this is only a type helper and is not the actual IDL. The original + * IDL can be found at `target/idl/balance_payment.json`. + */ +export type BalancePayment = { + "address": "GguVKxU88NUe3GLtns7Uaa6a8Pjb9USKq3WD1rjZnPS9", + "metadata": { + "name": "balancePayment", + "version": "0.1.0", + "spec": "0.1.0", + "description": "Created with Anchor" + }, + "instructions": [ + { + "name": "deposit", + "discriminator": [ + 242, + 35, + 198, + 137, + 82, + 225, + 242, + 182 + ], + "accounts": [ + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true, + "signer": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "initialize", + "discriminator": [ + 175, + 175, + 109, + 31, + 13, + 152, + 155, + 237 + ], + "accounts": [ + { + "name": "globalAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority" + }, + { + "name": "treasury" + }, + { + "name": "bot" + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "lock", + "discriminator": [ + 21, + 19, + 208, + 43, + 237, + 62, + 255, + 87 + ], + "accounts": [ + { + "name": "globalAccount", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "lockAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 76, + 79, + 67, + 75 + ] + }, + { + "kind": "account", + "path": "user" + }, + { + "kind": "account", + "path": "user_account.nonce", + "account": "userAccount" + } + ] + } + }, + { + "name": "vault", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "globalAccount" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "recoverInfo", + "type": { + "defined": { + "name": "ed25519RecoverInfo" + } + } + }, + { + "name": "amount", + "type": "u64" + } + ] + }, + { + "name": "pay", + "discriminator": [ + 119, + 18, + 216, + 65, + 192, + 117, + 122, + 220 + ], + "accounts": [ + { + "name": "globalAccount", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "globalAccount" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "recoverInfo", + "type": { + "defined": { + "name": "ed25519RecoverInfo" + } + } + }, + { + "name": "amountToTransfer", + "type": "u64" + } + ] + }, + { + "name": "register", + "discriminator": [ + 211, + 124, + 67, + 15, + 211, + 194, + 178, + 240 + ], + "accounts": [ + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "signer": true + }, + { + "name": "vault", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [] + }, + { + "name": "setBot", + "discriminator": [ + 136, + 185, + 99, + 236, + 200, + 131, + 204, + 118 + ], + "accounts": [ + { + "name": "globalAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority", + "signer": true, + "relations": [ + "globalAccount" + ] + }, + { + "name": "bot" + }, + { + "name": "payer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "setTreasury", + "discriminator": [ + 57, + 97, + 196, + 95, + 195, + 206, + 106, + 136 + ], + "accounts": [ + { + "name": "globalAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "authority", + "signer": true, + "relations": [ + "globalAccount" + ] + }, + { + "name": "treasury" + }, + { + "name": "payer", + "writable": true, + "signer": true + } + ], + "args": [] + }, + { + "name": "settle", + "discriminator": [ + 175, + 42, + 185, + 87, + 144, + 131, + 102, + 212 + ], + "accounts": [ + { + "name": "globalAccount", + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 71, + 76, + 79, + 66, + 65, + 76 + ] + } + ] + } + }, + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true + }, + { + "name": "treasury", + "writable": true + }, + { + "name": "lockAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 76, + 79, + 67, + 75 + ] + }, + { + "kind": "account", + "path": "user" + }, + { + "kind": "arg", + "path": "nonce" + } + ] + } + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "bot", + "signer": true, + "relations": [ + "globalAccount" + ] + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "nonce", + "type": "u64" + }, + { + "name": "amountToTransfer", + "type": "u64" + } + ] + }, + { + "name": "withdraw", + "discriminator": [ + 183, + 18, + 70, + 156, + 148, + 109, + 161, + 34 + ], + "accounts": [ + { + "name": "userAccount", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 85, + 83, + 69, + 82 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "user", + "writable": true, + "signer": true + }, + { + "name": "vault", + "writable": true, + "pda": { + "seeds": [ + { + "kind": "const", + "value": [ + 86, + 65, + 85, + 76, + 84 + ] + }, + { + "kind": "account", + "path": "user" + } + ] + } + }, + { + "name": "payer", + "writable": true, + "signer": true + }, + { + "name": "systemProgram", + "address": "11111111111111111111111111111111" + } + ], + "args": [ + { + "name": "amount", + "type": "u64" + } + ] + } + ], + "accounts": [ + { + "name": "globalAccount", + "discriminator": [ + 129, + 105, + 124, + 171, + 189, + 42, + 108, + 69 + ] + }, + { + "name": "lockAccount", + "discriminator": [ + 223, + 64, + 71, + 124, + 255, + 86, + 118, + 192 + ] + }, + { + "name": "userAccount", + "discriminator": [ + 211, + 33, + 136, + 16, + 186, + 110, + 242, + 127 + ] + } + ], + "errors": [ + { + "code": 6000, + "name": "unauthorized", + "msg": "Unauthorized access." + }, + { + "code": 6001, + "name": "insufficientFunds", + "msg": "Insufficient funds." + }, + { + "code": 6002, + "name": "signatureFormatInvalid", + "msg": "The signature format or recovery ID is incorrect." + }, + { + "code": 6003, + "name": "signatureRecoveryFailed", + "msg": "Failed to recover public key from signature." + }, + { + "code": 6004, + "name": "signatureMismatch", + "msg": "The recovered public key does not match the user's public key." + }, + { + "code": 6005, + "name": "signatureExpired", + "msg": "The signature is expired." + } + ], + "types": [ + { + "name": "ed25519RecoverInfo", + "type": { + "kind": "struct", + "fields": [ + { + "name": "signature", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "payload", + "type": { + "array": [ + "u8", + 64 + ] + } + }, + { + "name": "deadline", + "type": "i64" + } + ] + } + }, + { + "name": "globalAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "authority", + "type": "pubkey" + }, + { + "name": "bot", + "type": "pubkey" + }, + { + "name": "treasury", + "type": "pubkey" + } + ] + } + }, + { + "name": "lockAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "amount", + "type": "u64" + } + ] + } + }, + { + "name": "userAccount", + "type": { + "kind": "struct", + "fields": [ + { + "name": "nonce", + "type": "u64" + }, + { + "name": "lockedAmount", + "type": "u64" + }, + { + "name": "vault", + "type": "pubkey" + } + ] + } + } + ] +}; diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/bin/eligible-checker b/dephy-vending_machine-examples/balance-payment/bot_example_js/bin/eligible-checker new file mode 100755 index 0000000..5ec95d3 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/bin/eligible-checker @@ -0,0 +1,8 @@ +#!/bin/bash + +USER=$1 +AMOUNT=$2 +NONCE=$3 +RECOVER_INFO=$4 + +exec bun run /opt/balance-payment-bot/index.ts check_eligible --net devnet --rpc "https://api.devnet.solana.com" --user "$USER" --amount "$AMOUNT" --nonce "$NONCE" --recoverInfo "$RECOVER_INFO" diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/bin/locker b/dephy-vending_machine-examples/balance-payment/bot_example_js/bin/locker new file mode 100755 index 0000000..765c2c2 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/bin/locker @@ -0,0 +1,7 @@ +#!/bin/bash + +USER=$1 +AMOUNT=$2 +RECOVER_INFO=$3 + +exec bun run /opt/balance-payment-bot/index.ts lock --net devnet --rpc "https://api.devnet.solana.com" --keypair /opt/balance-payment-bot/bot.demo.json --user "$USER" --amount "$AMOUNT" --recoverInfo "$RECOVER_INFO" diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/bin/settler b/dephy-vending_machine-examples/balance-payment/bot_example_js/bin/settler new file mode 100755 index 0000000..7ccab28 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/bin/settler @@ -0,0 +1,7 @@ +#!/bin/bash + +USER=$1 +NONCE=$2 +AMOUNT_TO_TRANSFER=$3 + +exec bun run /opt/balance-payment-bot/index.ts settle --net devnet --rpc "https://api.devnet.solana.com" --keypair /opt/balance-payment-bot/bot.demo.json --user "$USER" --nonce "$NONCE" --amountToTransfer "$AMOUNT_TO_TRANSFER" diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/index.ts b/dephy-vending_machine-examples/balance-payment/bot_example_js/index.ts new file mode 100644 index 0000000..eb62492 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/index.ts @@ -0,0 +1,618 @@ +import * as anchor from "@coral-xyz/anchor"; +import * as ed from "@noble/ed25519"; +import { web3, Program, BN } from "@coral-xyz/anchor"; +import { BalancePayment } from "./balance_payment"; +import BalancePaymentIDL from "./balance_payment.json"; +import { Command } from "commander"; +import { v4 as uuidv4 } from "uuid"; +import { + Connection, + Keypair, + SendTransactionError, + TransactionExpiredTimeoutError, +} from "@solana/web3.js"; +import keccak from "keccak"; +import { readFileSync } from "fs"; +import os from "os"; +import path from "path"; +import bs58 from "bs58"; + +const cli = new Command(); + +const initializeProviderAndProgram = ( + net: string, + rpc?: string, + keypairPath?: string +) => { + if (net !== "devnet" && net !== "mainnet-beta") { + throw new Error("net must be devnet or mainnet-beta"); + } + + const rpcEndpoint = rpc ?? web3.clusterApiUrl(net); + const connection = new web3.Connection(rpcEndpoint, "confirmed"); + + let provider: anchor.Provider; + let keypair: web3.Keypair | null = null; + + if (keypairPath) { + keypair = getKeypair(keypairPath); + const wallet = new anchor.Wallet(keypair); + provider = new anchor.AnchorProvider(connection, wallet, { + commitment: "confirmed", + }); + } else { + provider = new anchor.AnchorProvider(connection, {} as anchor.Wallet, { + commitment: "confirmed", + }); + } + + anchor.setProvider(provider); + + const program = new Program( + { + ...BalancePaymentIDL, + address: BalancePaymentIDL.address, + } as BalancePayment, + provider + ); + + return { + keypair, // 如果没有 keypairPath,这里会返回 null + provider, + program, + }; +}; + +type Methods = anchor.Program["methods"]; + +const execute = async (tx: ReturnType) => { + const pubkeys = await tx.pubkeys(); + for (const [name, key] of Object.entries(pubkeys)) { + console.log(name, key.toBase58()); + } + const signature = await tx.rpc(); + console.log("signature", signature); + return { signature, pubkeys }; +}; + +const sol = (n: number | string) => { + return new BN(Number(n) * web3.LAMPORTS_PER_SOL); +}; + +const generate64ByteUUIDPayload = (): Buffer => { + const uuid = uuidv4().replace(/-/g, ""); + const uuidBuffer = Buffer.from(uuid, "hex"); + const extendedBuffer = Buffer.concat([uuidBuffer, Buffer.alloc(48, 0)]); + return extendedBuffer; +}; + +const getKeypair = (keypairPath?: string): Keypair => { + // Default path: ~/.config/solana/id.json + const defaultPath = path.join(os.homedir(), ".config", "solana", "id.json"); + const resolvedPath = keypairPath || defaultPath; + + try { + const keypairFile = readFileSync(resolvedPath, "utf-8"); + const keypair = Keypair.fromSecretKey(Buffer.from(JSON.parse(keypairFile))); + return keypair; + } catch (error) { + throw new Error( + `Failed to load keypair from ${resolvedPath}: ${error.message}` + ); + } +}; + +const getUserAccountPubkey = (user: web3.PublicKey) => { + const [userAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("USER"), user.toBuffer()], + new web3.PublicKey(BalancePaymentIDL.address) + ); + return userAccountPubkey; +}; + +async function confirmTransaction(connection, txHash) { + const maxRetries = 10; + const retryInterval = 3000; + + for (let i = 0; i < maxRetries; i++) { + const status = await connection.getSignatureStatus(txHash); + if ( + status && + status.value && + status.value.confirmationStatus === "finalized" + ) { + return "finalized"; + } + console.log( + `Transaction not finalized yet. Retrying in ${ + retryInterval / 1000 + } seconds...` + ); + await sleep(retryInterval); + } + + return "failed"; +} + +function sleep(ms: number) { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +const SUCCESS = 0; +const NETWORK_ERROR = 1; +const PARAMS_ERROR = 11; +const TRANSACTION_SEND_ERROR = 101; +const TRANSACTION_NOT_CONFIRMED = 102; +const TRANSACTION_UNKNOWN_ERROR = 103; + +const SIGN_MESSAGE_PREFIX = "DePHY vending machine/Example:\n"; + +cli.name("cli"); + +cli + .command("sign_message") + .requiredOption("--net ", "devnet | mainnet-beta") + .option("--rpc ", "rpc url link") + .requiredOption( + "--keypair ", + "Path to keypair file (default: ~/.config/solana/id.json)" + ) + .requiredOption("--minutes ", "Minutes until deadline") + .action(async (opt) => { + const { keypair: userKeypair, program } = initializeProviderAndProgram( + opt.net, + opt.rpc, + opt.keypair + ); + + const user = userKeypair.publicKey; // Use the public key from the provided keypair + + // Log the user who is signing + console.log("Signing user:", user.toBase58()); + + // Get nonce from user account + const userAccountPubkey = getUserAccountPubkey(user); + const userAccount = await program.account.userAccount.fetch( + userAccountPubkey + ); + + console.log("Signing nonce:", userAccount.nonce.toNumber()); + + // Convert minutes to deadline (current timestamp + minutes * 60 seconds) + const currentTimestamp = Math.floor(Date.now() / 1000); + const deadline = new BN(currentTimestamp + Number(opt.minutes) * 60); + + // Generate payload + const payload = generate64ByteUUIDPayload(); + + // Create message + const message = Buffer.concat([ + payload, + userAccount.nonce.toArrayLike(Buffer, "le", 8), + deadline.toArrayLike(Buffer, "le", 8), + ]); + + // Hash the message and generate digest + const messageHash = keccak("keccak256").update(message).digest(); + const hashedMessageBase58 = bs58.encode(messageHash); + const digest = new TextEncoder().encode( + `${SIGN_MESSAGE_PREFIX}${hashedMessageBase58}` + ); + + // Get user's private key + const privateKey = userKeypair.secretKey.slice(0, 32); // First 32 bytes are the private key + + // Sign the message + const signature = await ed.signAsync(digest, privateKey); + + // Create recoverInfo + const recoverInfo = { + signature: Array.from(signature), + payload: Array.from(payload), + deadline, + }; + + // Output recoverInfo as JSON + const jsonString = JSON.stringify(recoverInfo); + console.log("Recover Info (JSON):", jsonString); + + const base64String = Buffer.from(jsonString).toString("base64"); + console.log("Recover Info (Base64):", base64String); + }); + +cli + .command("check_eligible") + .requiredOption("--net ", "devnet | mainnet-beta") + .option("--rpc ", "rpc url link") + .requiredOption("--user ", "User Pubkey") + .requiredOption("--nonce ", "Nonce from request paylaod") + .requiredOption("--amount ", "Amount in SOL") + .requiredOption("--recoverInfo ", "Recover Info (Base64)") + .action(async (opt) => { + const check = async (opt) => { + try { + const lockAmount = sol(opt.amount); + const recoverInfo = JSON.parse( + Buffer.from(opt.recoverInfo, "base64").toString() + ); + const userPubkey = new web3.PublicKey(opt.user); + + const { program, provider } = initializeProviderAndProgram( + opt.net, + opt.rpc, + opt.keypair + ); + + const userAccountPubkey = getUserAccountPubkey(userPubkey); + + const userAccount = await program.account.userAccount.fetch( + userAccountPubkey + ); + + // 0.check nonce from request payload whether equal to nonce on chain + if (userAccount.nonce.toNumber() !== parseInt(opt.nonce, 10)) { + return false; + } + + // 1.concat message, nonce is from blockchain + const message = Buffer.concat([ + Buffer.from(recoverInfo.payload), + userAccount.nonce.toArrayLike(Buffer, "le", 8), + new BN(recoverInfo.deadline, "hex").toArrayLike(Buffer, "le", 8), + ]); + + // 2.hash message and generate digest + const messageHash = keccak("keccak256").update(message).digest(); + const hashedMessageBase58 = bs58.encode(messageHash); + const digest = new TextEncoder().encode( + `${SIGN_MESSAGE_PREFIX}${hashedMessageBase58}` + ); + + // 3.verify signature source + const isValid = await ed.verifyAsync( + Buffer.from(recoverInfo.signature), + digest, + userPubkey.toBytes() + ); + if (!isValid) { + return false; + } + + // 4.verify deadline expiration + const currentTimestamp = Math.floor(Date.now() / 1000); + const deadlineTimestamp = new BN( + recoverInfo.deadline, + "hex" + ).toNumber(); + if (currentTimestamp >= deadlineTimestamp) { + return false; + } + + // 5.verify available balance + const userVaultBalance = new BN( + await provider.connection.getBalance(userAccount.vault) + ); + const availableBalance = userVaultBalance.sub(userAccount.lockedAmount); + if (availableBalance.lt(lockAmount)) { + return false; + } + + return true; + } catch (e) { + console.error("check eligibility error happened,", e); + return false; + } + }; + const result = await check(opt); + console.log(result); + process.exit(result ? 0 : 1); + }); + +cli + .command("lock") + .requiredOption("--net ", "devnet | mainnet-beta") + .option("--rpc ", "rpc url link") + .requiredOption( + "--keypair ", + "Path to keypair file (default: ~/.config/solana/id.json)" + ) + .requiredOption("--user ", "User Pubkey") + .requiredOption("--amount ", "Amount in SOL") + .requiredOption("--recoverInfo ", "Recover Info (Base64)") + .action(async (opt) => { + const { program } = initializeProviderAndProgram( + opt.net, + opt.rpc, + opt.keypair + ); + + let user: web3.PublicKey, nonce: BN, amount: BN, recoverInfo: any; + try { + user = new web3.PublicKey(opt.user); + nonce = new BN(opt.nonce); + amount = sol(opt.amount); + recoverInfo = JSON.parse( + Buffer.from(opt.recoverInfo, "base64").toString() + ); + } catch (error) { + console.error("Parameter parsing error:", error); + process.exit(PARAMS_ERROR); // 参数解析错误 + } + + // 处理 recoverInfo + try { + recoverInfo.signature = Array.from(recoverInfo.signature); + recoverInfo.payload = Array.from(recoverInfo.payload); + recoverInfo.deadline = new BN(recoverInfo.deadline, "hex"); + } catch (error) { + console.error("RecoverInfo parsing error:", error); + process.exit(PARAMS_ERROR); // 参数解析错误 + } + + const [globalAccountPubkey] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("GLOBAL")], + program.programId + ); + let globalAccount: any; + try { + globalAccount = await program.account.globalAccount.fetch( + globalAccountPubkey + ); + } catch (error) { + console.error("Failed to fetch global account:", error); + process.exit(NETWORK_ERROR); // 网络或账户获取错误 + } + + const tx = program.methods.lock(recoverInfo, amount).accountsPartial({ + user, + bot: globalAccount.bot, + }); + + try { + await execute(tx); + console.log("Lock transaction completed successfully."); + } catch (error) { + if (error instanceof SendTransactionError) { + console.error("Smart contract reverted:", error); + process.exit(TRANSACTION_SEND_ERROR); // 交易发送失败 + } else if (error instanceof TransactionExpiredTimeoutError) { + const txHash = error.signature; + console.log( + `Transaction expired but may have succeeded. Checking status for tx hash: ${txHash}` + ); + + const connection = new Connection( + opt.rpc || "https://api.devnet.solana.com" + ); + const status = await confirmTransaction(connection, txHash); + + if (status === "finalized") { + console.log("Transaction finalized successfully."); + } else { + console.error("Transaction failed or could not be finalized."); + process.exit(TRANSACTION_NOT_CONFIRMED); + } + } else { + console.error("Error during lock transaction:", error); + process.exit(TRANSACTION_UNKNOWN_ERROR); + } + } + + process.exit(SUCCESS); + }); + +cli + .command("settle") + .requiredOption("--net ", "devnet | mainnet-beta") + .option("--rpc ", "rpc url link") + .requiredOption( + "--keypair ", + "Path to keypair file (default: ~/.config/solana/id.json)" + ) + .requiredOption("--user ", "User Pubkey") + .requiredOption("--nonce ", "Nonce") + .requiredOption("--amountToTransfer ", "Amount in SOL") + .action(async (opt) => { + const { program } = initializeProviderAndProgram( + opt.net, + opt.rpc, + opt.keypair + ); + + let user: web3.PublicKey, nonce: BN, amountToTransfer: BN; + try { + user = new web3.PublicKey(opt.user); + nonce = new BN(opt.nonce); + amountToTransfer = sol(opt.amountToTransfer); + } catch (error) { + console.error("Parameter parsing error:", error); + process.exit(PARAMS_ERROR); + } + + let globalAccountPubkey: web3.PublicKey, globalAccount: any; + try { + [globalAccountPubkey] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("GLOBAL")], + program.programId + ); + globalAccount = await program.account.globalAccount.fetch( + globalAccountPubkey + ); + } catch (error) { + console.error("Failed to fetch global account:", error); + process.exit(NETWORK_ERROR); + } + + let userAccountPubkey: web3.PublicKey, userAccount: any; + try { + userAccountPubkey = getUserAccountPubkey(userAccountPubkey); + userAccount = await program.account.userAccount.fetch(userAccountPubkey); + } catch (error) { + console.error("Failed to fetch user account:", error); + process.exit(NETWORK_ERROR); + } + + if (nonce.gte(userAccount.nonce)) { + console.error( + `nonce too large: ${nonce.toNumber()} >= ${userAccount.nonce.toNumber()}}` + ); + process.exit(PARAMS_ERROR); + } + + const [lockAccountPubkey] = web3.PublicKey.findProgramAddressSync( + [ + Buffer.from("LOCK"), + user.toBuffer(), + nonce.toArrayLike(Buffer, "le", 8), + ], + program.programId + ); + try { + await program.account.lockAccount.fetch(lockAccountPubkey); + } catch (error) { + if ( + error.message.includes("Account does not exist") && + nonce.lt(userAccount.nonce) + ) { + console.log("Lock already been settled"); + process.exit(SUCCESS); + } else { + console.error("Fetch lock account error:", error); + process.exit(NETWORK_ERROR); + } + } + + const tx = program.methods.settle(nonce, amountToTransfer).accountsPartial({ + user, + treasury: globalAccount.treasury, + bot: globalAccount.bot, + }); + + try { + await execute(tx); + console.log("Settle transaction completed successfully."); + } catch (error) { + if (error instanceof SendTransactionError) { + console.error("Smart contract reverted:", error); + process.exit(TRANSACTION_SEND_ERROR); + } else if (error instanceof TransactionExpiredTimeoutError) { + const txHash = error.signature; + console.log( + `Transaction expired but may have succeeded. Checking status for tx hash: ${txHash}` + ); + + const connection = new Connection( + opt.rpc || "https://api.devnet.solana.com" + ); + const status = await confirmTransaction(connection, txHash); + + if (status === "finalized") { + console.log("Transaction finalized successfully."); + } else { + console.error("Transaction failed or could not be finalized."); + process.exit(TRANSACTION_NOT_CONFIRMED); // 返回非零退出码表示失败 + } + } else { + console.error("Error during settle transaction:", error); + process.exit(TRANSACTION_UNKNOWN_ERROR); // 返回非零退出码表示失败 + } + } + + process.exit(SUCCESS); + }); + +cli + .command("pay") + .requiredOption("--net ", "devnet | mainnet-beta") + .option("--rpc ", "rpc url link") + .requiredOption( + "--keypair ", + "Path to keypair file (default: ~/.config/solana/id.json)" + ) + .requiredOption("--user ", "User Pubkey") + .requiredOption("--amountToTransfer ", "Amount in SOL") + .requiredOption("--recoverInfo ", "Recover Info (Base64)") + .action(async (opt) => { + const { program } = initializeProviderAndProgram( + opt.net, + opt.rpc, + opt.keypair + ); + + let user: web3.PublicKey, nonce: BN, amountToTransfer: BN, recoverInfo: any; + try { + user = new web3.PublicKey(opt.user); + nonce = new BN(opt.nonce); + amountToTransfer = sol(opt.amountToTransfer); + recoverInfo = JSON.parse( + Buffer.from(opt.recoverInfo, "base64").toString() + ); + } catch (error) { + console.error("Parameter parsing error:", error); + process.exit(PARAMS_ERROR); // 参数解析错误 + } + + // 处理 recoverInfo + try { + recoverInfo.signature = Array.from(recoverInfo.signature); + recoverInfo.payload = Array.from(recoverInfo.payload); + recoverInfo.deadline = new BN(recoverInfo.deadline, "hex"); + } catch (error) { + console.error("RecoverInfo parsing error:", error); + process.exit(PARAMS_ERROR); // 参数解析错误 + } + + const [globalAccountPubkey] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("GLOBAL")], + program.programId + ); + let globalAccount: any; + try { + globalAccount = await program.account.globalAccount.fetch( + globalAccountPubkey + ); + } catch (error) { + console.error("Failed to fetch global account:", error); + process.exit(NETWORK_ERROR); // 网络或账户获取错误 + } + + const tx = program.methods.pay(recoverInfo, amountToTransfer).accountsPartial({ + user, + treasury: globalAccount.treasury, + bot: globalAccount.bot, + }); + + try { + await execute(tx); + console.log("Pay transaction completed successfully."); + } catch (error) { + if (error instanceof SendTransactionError) { + console.error("Smart contract reverted:", error); + process.exit(TRANSACTION_SEND_ERROR); // 交易发送失败 + } else if (error instanceof TransactionExpiredTimeoutError) { + const txHash = error.signature; + console.log( + `Transaction expired but may have succeeded. Checking status for tx hash: ${txHash}` + ); + + const connection = new Connection( + opt.rpc || "https://api.devnet.solana.com" + ); + const status = await confirmTransaction(connection, txHash); + + if (status === "finalized") { + console.log("Transaction finalized successfully."); + } else { + console.error("Transaction failed or could not be finalized."); + process.exit(TRANSACTION_NOT_CONFIRMED); + } + } else { + console.error("Error during lock transaction:", error); + process.exit(TRANSACTION_UNKNOWN_ERROR); + } + } + + process.exit(SUCCESS); + }); + +cli.parse(); diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/package.json b/dephy-vending_machine-examples/balance-payment/bot_example_js/package.json new file mode 100644 index 0000000..cd0150b --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/package.json @@ -0,0 +1,27 @@ +{ + "license": "ISC", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@coral-xyz/anchor": "^0.31.0", + "@noble/ed25519": "^2.2.2", + "@solana/web3.js": "^1.98.0", + "bs58": "^6.0.0", + "commander": "^13.0.0", + "keccak": "^3.0.4" + }, + "devDependencies": { + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/keccak": "^3.0.5", + "@types/mocha": "^9.0.0", + "@types/secp256k1": "^4.0.6", + "chai": "^4.3.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^4.3.5" + } +} diff --git a/dephy-vending_machine-examples/balance-payment/bot_example_js/tsconfig.json b/dephy-vending_machine-examples/balance-payment/bot_example_js/tsconfig.json new file mode 100644 index 0000000..247d160 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/bot_example_js/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "commonjs", + "target": "es6", + "esModuleInterop": true, + "resolveJsonModule": true + } +} diff --git a/dephy-vending_machine-examples/balance-payment/migrations/deploy.ts b/dephy-vending_machine-examples/balance-payment/migrations/deploy.ts new file mode 100644 index 0000000..82fb175 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/migrations/deploy.ts @@ -0,0 +1,12 @@ +// Migrations are an early feature. Currently, they're nothing more than this +// single deploy script that's invoked from the CLI, injecting a provider +// configured from the workspace's Anchor.toml. + +const anchor = require("@coral-xyz/anchor"); + +module.exports = async function (provider) { + // Configure client to use the provider. + anchor.setProvider(provider); + + // Add your deploy script here. +}; diff --git a/dephy-vending_machine-examples/balance-payment/package.json b/dephy-vending_machine-examples/balance-payment/package.json new file mode 100644 index 0000000..14a4860 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/package.json @@ -0,0 +1,30 @@ +{ + "license": "ISC", + "scripts": { + "lint:fix": "prettier */*.js \"*/**/*{.js,.ts}\" -w", + "lint": "prettier */*.js \"*/**/*{.js,.ts}\" --check" + }, + "dependencies": { + "@coral-xyz/anchor": "^0.31.0", + "@solana/web3.js": "^1.98.0" + }, + "devDependencies": { + "@noble/ed25519": "^2.2.2", + "@types/bn.js": "^5.1.0", + "@types/chai": "^4.3.0", + "@types/keccak": "^3.0.5", + "@types/mocha": "^9.0.0", + "@types/secp256k1": "^4.0.6", + "bs58": "^6.0.0", + "chai": "^4.3.4", + "commander": "^13.0.0", + "keccak": "^3.0.4", + "mocha": "^9.0.3", + "prettier": "^2.6.2", + "ts-mocha": "^10.0.0", + "typescript": "^4.3.5" + }, + "overrides": { + "@solana/buffer-layout": "^4.0.1" + } +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/Cargo.toml b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/Cargo.toml new file mode 100644 index 0000000..44c9089 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "balance-payment" +version = "0.1.0" +description = "Created with Anchor" +edition = "2021" + +[lib] +crate-type = ["cdylib", "lib"] +name = "balance_payment" + +[features] +default = [] +cpi = ["no-entrypoint"] +no-entrypoint = [] +no-idl = [] +no-log-ix-name = [] +idl-build = ["anchor-lang/idl-build"] + +[dependencies] +anchor-lang = { version = "0.31.0" } +anyhow = "1" +arrayref = "*" +bs58 = "0.4" +curve25519-dalek = { version = "4", default-features = false } +sha2 = "0.10.8" +solana-zk-token-sdk = "^2.0.2" diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/Xargo.toml b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/Xargo.toml new file mode 100644 index 0000000..475fb71 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/Xargo.toml @@ -0,0 +1,2 @@ +[target.bpfel-unknown-unknown.dependencies.std] +features = [] diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/keypair.json b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/keypair.json new file mode 100644 index 0000000..9c16f48 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/keypair.json @@ -0,0 +1 @@ +[118,171,22,138,219,238,43,55,2,144,166,47,140,179,126,103,91,80,241,45,49,251,228,181,187,228,111,60,141,175,91,161,233,24,77,228,82,49,123,133,27,66,243,147,119,224,89,94,109,109,160,165,223,142,1,104,207,96,236,176,122,11,134,82] diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/constants.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/constants.rs new file mode 100644 index 0000000..ccb0955 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/constants.rs @@ -0,0 +1,2 @@ +pub const DISCRIMINATOR_SIZE: usize = 8; +pub const SIGN_MESSAGE_PREFIX: &[u8; 31] = b"DePHY vending machine/Example:\n"; diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/errors.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/errors.rs new file mode 100644 index 0000000..3803c8e --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/errors.rs @@ -0,0 +1,17 @@ +use anchor_lang::error_code; + +#[error_code] +pub enum CustomError { + #[msg("Unauthorized access.")] + Unauthorized, + #[msg("Insufficient funds.")] + InsufficientFunds, + #[msg("The signature format or recovery ID is incorrect.")] + SignatureFormatInvalid, + #[msg("Failed to recover public key from signature.")] + SignatureRecoveryFailed, + #[msg("The recovered public key does not match the user's public key.")] + SignatureMismatch, + #[msg("The signature is expired.")] + SignatureExpired, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/deposit.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/deposit.rs new file mode 100644 index 0000000..25eb90f --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/deposit.rs @@ -0,0 +1,33 @@ +use crate::state::UserAccount; +use anchor_lang::{prelude::*, system_program}; + +pub fn deposit(ctx: Context, amount: u64) -> Result<()> { + system_program::transfer( + CpiContext::new_with_signer( + ctx.accounts.system_program.to_account_info(), + system_program::Transfer { + from: ctx.accounts.user.to_account_info(), + to: ctx.accounts.vault.to_account_info(), + }, + &[], + ), + amount, + )?; + + Ok(()) +} + + +#[derive(Accounts)] +pub struct Deposit<'info> { + #[account(mut, seeds = [b"USER", user.key.as_ref()], bump)] + pub user_account: Account<'info, UserAccount>, + #[account(mut)] + pub user: Signer<'info>, + /// CHECK: + #[account(mut, seeds = [b"VAULT", user.key().as_ref()], bump)] + pub vault: UncheckedAccount<'info>, + #[account(mut)] + pub payer: Signer<'info>, + pub system_program: Program<'info, System>, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/initialize.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/initialize.rs new file mode 100644 index 0000000..7447a96 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/initialize.rs @@ -0,0 +1,29 @@ +use crate::constants::DISCRIMINATOR_SIZE; +use crate::state::GlobalAccount; +use anchor_lang::prelude::*; + +pub fn initialize(ctx: Context) -> Result<()> { + let global_account = &mut ctx.accounts.global_account; + global_account.authority = ctx.accounts.authority.key(); + global_account.bot = ctx.accounts.bot.key(); + global_account.treasury = ctx.accounts.treasury.key(); + Ok(()) +} + +#[derive(Accounts)] +pub struct Initialize<'info> { + #[account(init, payer = payer, space = DISCRIMINATOR_SIZE + GlobalAccount::INIT_SPACE, seeds = [b"GLOBAL"], bump)] + pub global_account: Account<'info, GlobalAccount>, + /// CHECK: + #[account(constraint = authority.data_is_empty())] + pub authority: UncheckedAccount<'info>, + /// CHECK: + #[account(constraint = treasury.data_is_empty())] + pub treasury: UncheckedAccount<'info>, + /// CHECK: + #[account(constraint = bot.data_is_empty())] + pub bot: UncheckedAccount<'info>, + #[account(mut)] + pub payer: Signer<'info>, + pub system_program: Program<'info, System>, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/lock.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/lock.rs new file mode 100644 index 0000000..293b94a --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/lock.rs @@ -0,0 +1,98 @@ +use crate::{ + constants::{self, DISCRIMINATOR_SIZE}, + errors::CustomError, + state::{GlobalAccount, LockAccount, UserAccount}, + utils, +}; +use anchor_lang::{prelude::*, solana_program::keccak}; +use bs58; + +pub fn lock(ctx: Context, recover_info: ED25519RecoverInfo, amount: u64) -> Result<()> { + let user_account = &mut ctx.accounts.user_account; + let lock_account = &mut ctx.accounts.lock_account; + + recover_info.verify(user_account.nonce, &ctx.accounts.user.key())?; + + require!( + ctx.accounts.vault.get_lamports() - user_account.locked_amount >= amount, + CustomError::InsufficientFunds + ); + + user_account.nonce += 1; + user_account.locked_amount += amount; + + lock_account.amount = amount; + + Ok(()) +} + +#[derive(Accounts)] +pub struct Lock<'info> { + #[account(has_one = bot @ CustomError::Unauthorized, seeds = [b"GLOBAL"], bump)] + pub global_account: Account<'info, GlobalAccount>, + #[account(mut, seeds = [b"USER", user.key.as_ref()], bump)] + pub user_account: Account<'info, UserAccount>, + /// CHECK: + #[account(mut)] + pub user: UncheckedAccount<'info>, + #[account( + init, + payer = payer, + space = DISCRIMINATOR_SIZE + LockAccount::INIT_SPACE, + seeds = [b"LOCK", user.key().as_ref(), user_account.nonce.to_le_bytes().as_ref()], + bump, + )] + pub lock_account: Account<'info, LockAccount>, + /// CHECK: + #[account(seeds = [b"VAULT", user.key().as_ref()], bump)] + pub vault: UncheckedAccount<'info>, + pub bot: Signer<'info>, + #[account(mut)] + pub payer: Signer<'info>, + pub system_program: Program<'info, System>, +} + +#[derive(Debug, Clone, AnchorSerialize, AnchorDeserialize)] +pub struct ED25519RecoverInfo { + pub signature: [u8; 64], + pub payload: [u8; 64], + pub deadline: i64, +} + +impl ED25519RecoverInfo { + pub fn verify(&self, nonce: u64, pubkey: &Pubkey) -> Result<()> { + let message = { + let mut data = self.payload.to_vec(); + data.extend_from_slice(&nonce.to_le_bytes()); + data.extend_from_slice(&self.deadline.to_le_bytes()); + data + }; + + let hashed_message = { + let mut hasher = keccak::Hasher::default(); + hasher.hash(&message); + hasher.result().to_bytes() + }; + + let hashed_message_base58 = bs58::encode(&hashed_message).into_vec(); + + let digest = { + let mut data = constants::SIGN_MESSAGE_PREFIX.to_vec(); // 前缀转换为 Vec + data.extend_from_slice(&hashed_message_base58); // 添加 Base58 编码的哈希值 + data + }; + + let valid = utils::verify_signature(pubkey, &self.signature, &digest) + .map_err(|_| CustomError::SignatureFormatInvalid)?; + + require!(valid, CustomError::SignatureMismatch); + + let clock = Clock::get()?; + require!( + clock.unix_timestamp <= self.deadline, + CustomError::SignatureExpired + ); + + Ok(()) + } +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/mod.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/mod.rs new file mode 100644 index 0000000..77c4668 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/mod.rs @@ -0,0 +1,19 @@ +pub mod initialize; +pub mod set_bot; +pub mod set_treasury; +pub mod register; +pub mod deposit; +pub mod withdraw; +pub mod lock; +pub mod settle; +pub mod pay; + +pub use initialize::*; +pub use set_bot::*; +pub use set_treasury::*; +pub use register::*; +pub use deposit::*; +pub use withdraw::*; +pub use lock::*; +pub use settle::*; +pub use pay::*; diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/pay.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/pay.rs new file mode 100644 index 0000000..121333b --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/pay.rs @@ -0,0 +1,63 @@ +use crate::{ + errors::CustomError, + state::{GlobalAccount, UserAccount}, +}; +use anchor_lang::{prelude::*, system_program}; + +use super::ED25519RecoverInfo; + +pub fn pay( + ctx: Context, + recover_info: ED25519RecoverInfo, + amount_to_transfer: u64, +) -> Result<()> { + let user_account = &mut ctx.accounts.user_account; + + recover_info.verify(user_account.nonce, &ctx.accounts.user.key())?; + + require!( + ctx.accounts.vault.get_lamports() - user_account.locked_amount >= amount_to_transfer, + CustomError::InsufficientFunds + ); + + system_program::transfer( + CpiContext::new_with_signer( + ctx.accounts.system_program.to_account_info(), + system_program::Transfer { + from: ctx.accounts.vault.to_account_info(), + to: ctx.accounts.treasury.to_account_info(), + }, + &[&[ + b"VAULT", + ctx.accounts.user.key().as_ref(), + &[ctx.bumps.vault], + ]], + ), + amount_to_transfer, + )?; + + user_account.nonce += 1; + + Ok(()) +} + +#[derive(Accounts)] +pub struct Pay<'info> { + #[account(has_one = bot @ CustomError::Unauthorized, seeds = [b"GLOBAL"], bump)] + pub global_account: Account<'info, GlobalAccount>, + #[account(mut, seeds = [b"USER", user.key.as_ref()], bump)] + pub user_account: Account<'info, UserAccount>, + /// CHECK: + #[account(mut)] + pub user: UncheckedAccount<'info>, + /// CHECK: + #[account(mut, constraint = treasury.key() == global_account.treasury)] + pub treasury: UncheckedAccount<'info>, + /// CHECK: + #[account(mut, seeds = [b"VAULT", user.key().as_ref()], bump)] + pub vault: UncheckedAccount<'info>, + pub bot: Signer<'info>, + #[account(mut)] + pub payer: Signer<'info>, + pub system_program: Program<'info, System>, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/register.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/register.rs new file mode 100644 index 0000000..74ca712 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/register.rs @@ -0,0 +1,24 @@ +use crate::constants::DISCRIMINATOR_SIZE; +use crate::state::UserAccount; +use anchor_lang::prelude::*; + +pub fn register(ctx: Context) -> Result<()> { + let user_account = &mut ctx.accounts.user_account; + user_account.nonce = 0; + user_account.locked_amount = 0; + user_account.vault = ctx.accounts.vault.key(); + Ok(()) +} + +#[derive(Accounts)] +pub struct Register<'info> { + #[account(init, payer = payer, space = DISCRIMINATOR_SIZE + UserAccount::INIT_SPACE, seeds = [b"USER", user.key.as_ref()], bump)] + pub user_account: Account<'info, UserAccount>, + pub user: Signer<'info>, + /// CHECK: vault is only used for store SOL + #[account(constraint = vault.data_is_empty(), seeds = [b"VAULT", user.key().as_ref()], bump)] + pub vault: UncheckedAccount<'info>, + #[account(mut)] + pub payer: Signer<'info>, + pub system_program: Program<'info, System>, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/set_bot.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/set_bot.rs new file mode 100644 index 0000000..923aecb --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/set_bot.rs @@ -0,0 +1,21 @@ +use crate::errors::CustomError; +use crate::state::GlobalAccount; +use anchor_lang::prelude::*; + +pub fn set_bot(ctx: Context) -> Result<()> { + let global_account = &mut ctx.accounts.global_account; + global_account.bot = ctx.accounts.bot.key(); + Ok(()) +} + +#[derive(Accounts)] +pub struct SetBot<'info> { + #[account(mut, has_one = authority @ CustomError::Unauthorized, seeds = [b"GLOBAL"], bump)] + pub global_account: Account<'info, GlobalAccount>, + pub authority: Signer<'info>, + /// CHECK: + #[account(constraint = bot.data_is_empty())] + pub bot: UncheckedAccount<'info>, + #[account(mut)] + pub payer: Signer<'info>, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/set_treasury.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/set_treasury.rs new file mode 100644 index 0000000..72a59e3 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/set_treasury.rs @@ -0,0 +1,21 @@ +use crate::errors::CustomError; +use crate::state::GlobalAccount; +use anchor_lang::prelude::*; + +pub fn set_treasury(ctx: Context) -> Result<()> { + let global_account = &mut ctx.accounts.global_account; + global_account.treasury = ctx.accounts.treasury.key(); + Ok(()) +} + +#[derive(Accounts)] +pub struct SetTreasury<'info> { + #[account(mut, has_one = authority @ CustomError::Unauthorized, seeds = [b"GLOBAL"], bump)] + pub global_account: Account<'info, GlobalAccount>, + pub authority: Signer<'info>, + /// CHECK: + #[account(constraint = treasury.data_is_empty())] + pub treasury: UncheckedAccount<'info>, + #[account(mut)] + pub payer: Signer<'info>, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/settle.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/settle.rs new file mode 100644 index 0000000..7c3370d --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/settle.rs @@ -0,0 +1,75 @@ +use crate::{ + errors::CustomError, + state::{GlobalAccount, LockAccount, UserAccount}, +}; +use anchor_lang::{prelude::*, system_program}; + +pub fn settle(ctx: Context, _nonce: u64, amount_to_transfer: u64) -> Result<()> { + let user_account = &mut ctx.accounts.user_account; + let lock_account = &mut ctx.accounts.lock_account; + + require!( + lock_account.amount >= amount_to_transfer, + CustomError::InsufficientFunds + ); + + user_account.locked_amount -= lock_account.amount; + + system_program::transfer( + CpiContext::new_with_signer( + ctx.accounts.system_program.to_account_info(), + system_program::Transfer { + from: ctx.accounts.vault.to_account_info(), + to: ctx.accounts.treasury.to_account_info(), + }, + &[&[ + b"VAULT", + ctx.accounts.user.key().as_ref(), + &[ctx.bumps.vault], + ]], + ), + amount_to_transfer, + )?; + + // Close the lock account and transfer the rent to the payer + let lock_account_info = lock_account.to_account_info(); + let payer_info = ctx.accounts.payer.to_account_info(); + let rent = Rent::get()?; + let lamports = rent.minimum_balance(lock_account_info.data_len()); + + **lock_account_info.lamports.borrow_mut() -= lamports; + **payer_info.lamports.borrow_mut() += lamports; + + lock_account_info.assign(&system_program::ID); + lock_account_info.realloc(0, false)?; + + Ok(()) +} + +#[derive(Accounts)] +#[instruction(nonce: u64)] +pub struct Settle<'info> { + #[account(has_one = bot @ CustomError::Unauthorized, seeds = [b"GLOBAL"], bump)] + pub global_account: Account<'info, GlobalAccount>, + #[account(mut, seeds = [b"USER", user.key.as_ref()], bump)] + pub user_account: Account<'info, UserAccount>, + /// CHECK: + #[account(mut)] + pub user: UncheckedAccount<'info>, + /// CHECK: + #[account(mut, constraint = treasury.key() == global_account.treasury)] + pub treasury: UncheckedAccount<'info>, + #[account( + mut, + seeds = [b"LOCK", user.key().as_ref(), nonce.to_le_bytes().as_ref()], + bump, + )] + pub lock_account: Account<'info, LockAccount>, + /// CHECK: + #[account(mut, seeds = [b"VAULT", user.key().as_ref()], bump)] + pub vault: UncheckedAccount<'info>, + pub bot: Signer<'info>, + #[account(mut)] + pub payer: Signer<'info>, + pub system_program: Program<'info, System>, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/withdraw.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/withdraw.rs new file mode 100644 index 0000000..a15e2c8 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/instructions/withdraw.rs @@ -0,0 +1,40 @@ +use crate::{errors::CustomError, state::UserAccount}; +use anchor_lang::{prelude::*, system_program}; + +pub fn withdraw(ctx: Context, amount: u64) -> Result<()> { + let available_balance = + ctx.accounts.vault.get_lamports() - ctx.accounts.user_account.locked_amount; + require!(available_balance >= amount, CustomError::InsufficientFunds); + + system_program::transfer( + CpiContext::new_with_signer( + ctx.accounts.system_program.to_account_info(), + system_program::Transfer { + from: ctx.accounts.vault.to_account_info(), + to: ctx.accounts.user.to_account_info(), + }, + &[&[ + b"VAULT", + ctx.accounts.user.key().as_ref(), + &[ctx.bumps.vault], + ]], + ), + amount, + )?; + + Ok(()) +} + +#[derive(Accounts)] +pub struct Withdraw<'info> { + #[account(mut, seeds = [b"USER", user.key.as_ref()], bump)] + pub user_account: Account<'info, UserAccount>, + #[account(mut)] + pub user: Signer<'info>, + /// CHECK: + #[account(mut, seeds = [b"VAULT", user.key().as_ref()], bump)] + pub vault: UncheckedAccount<'info>, + #[account(mut)] + pub payer: Signer<'info>, + pub system_program: Program<'info, System>, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/lib.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/lib.rs new file mode 100644 index 0000000..bde08a6 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/lib.rs @@ -0,0 +1,52 @@ +use anchor_lang::prelude::*; + +pub mod constants; +pub mod errors; +pub mod instructions; +pub mod state; +pub mod utils; + +use instructions::*; + +declare_id!("GguVKxU88NUe3GLtns7Uaa6a8Pjb9USKq3WD1rjZnPS9"); + +#[program] +pub mod balance_payment { + use super::*; + + pub fn initialize(ctx: Context) -> Result<()> { + instructions::initialize(ctx) + } + + pub fn set_bot(ctx: Context) -> Result<()> { + instructions::set_bot(ctx) + } + + pub fn set_treasury(ctx: Context) -> Result<()> { + instructions::set_treasury(ctx) + } + + pub fn register(ctx: Context) -> Result<()> { + instructions::register(ctx) + } + + pub fn deposit(ctx: Context, amount: u64) -> Result<()> { + instructions::deposit(ctx, amount) + } + + pub fn withdraw(ctx: Context, amount: u64) -> Result<()> { + instructions::withdraw(ctx, amount) + } + + pub fn lock(ctx: Context, recover_info: ED25519RecoverInfo, amount: u64) -> Result<()> { + instructions::lock(ctx, recover_info, amount) + } + + pub fn settle(ctx: Context, _nonce: u64, amount_to_transfer: u64) -> Result<()> { + instructions::settle(ctx, _nonce, amount_to_transfer) + } + + pub fn pay(ctx: Context, recover_info: ED25519RecoverInfo, amount_to_transfer: u64) -> Result<()> { + instructions::pay(ctx, recover_info, amount_to_transfer) + } +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/global.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/global.rs new file mode 100644 index 0000000..1fd8374 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/global.rs @@ -0,0 +1,9 @@ +use anchor_lang::prelude::*; + +#[account] +#[derive(InitSpace)] +pub struct GlobalAccount { + pub authority: Pubkey, + pub bot: Pubkey, + pub treasury: Pubkey, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/lock.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/lock.rs new file mode 100644 index 0000000..454eb33 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/lock.rs @@ -0,0 +1,7 @@ +use anchor_lang::prelude::*; + +#[account] +#[derive(InitSpace)] +pub struct LockAccount { + pub amount: u64, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/mod.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/mod.rs new file mode 100644 index 0000000..892ebc5 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/mod.rs @@ -0,0 +1,7 @@ +pub mod global; +pub mod user; +pub mod lock; + +pub use global::*; +pub use user::*; +pub use lock::*; diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/user.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/user.rs new file mode 100644 index 0000000..89cac1e --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/state/user.rs @@ -0,0 +1,9 @@ +use anchor_lang::prelude::*; + +#[account] +#[derive(InitSpace)] +pub struct UserAccount { + pub nonce: u64, + pub locked_amount: u64, + pub vault: Pubkey, +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/utils/ed25519.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/utils/ed25519.rs new file mode 100644 index 0000000..24e17c5 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/utils/ed25519.rs @@ -0,0 +1,51 @@ +// from https://github.com/stegaBOB/solana_ed25519_verify/blob/main/src/lib.rs + +use anchor_lang::solana_program::pubkey::Pubkey; +use anyhow::{bail, Context}; +use arrayref::array_ref; +use curve25519_dalek::scalar::Scalar; +use sha2::Digest; +use solana_zk_token_sdk::curve25519::{ + edwards::{multiply_edwards, subtract_edwards, validate_edwards, PodEdwardsPoint}, + scalar::PodScalar, +}; + +// funny number +const EDWARDS_BASE_POINT: PodEdwardsPoint = PodEdwardsPoint([ + 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +]); + +pub fn verify_signature( + pubkey: &Pubkey, + signature: &[u8; 64], + message: &[u8], +) -> anyhow::Result { + let a = PodEdwardsPoint(pubkey.to_bytes()); + let r = PodEdwardsPoint(*array_ref![signature, 0, 32]); + if !validate_edwards(&a) { + bail!("Pubkey is not a valid EdwardsPoint") + } + if !validate_edwards(&r) { + bail!("Signature R is not a valid EdwardsPoint") + } + + let s = array_ref![signature, 32, 32]; + let s_scalar = Scalar::from_bytes_mod_order(*s); + let s_scalar = PodScalar(s_scalar.to_bytes()); + + let mut hasher = sha2::Sha512::new(); + // R || A || M + hasher.update(r.0); + hasher.update(a.0); + hasher.update(message); + let hash_bytes = hasher.finalize(); + let hash_array = array_ref![hash_bytes, 0, 64]; + let h_scalar = Scalar::from_bytes_mod_order_wide(hash_array); + let h_scalar = PodScalar(h_scalar.to_bytes()); + + let s_b = multiply_edwards(&s_scalar, &EDWARDS_BASE_POINT).context("Failed to multiply S*B")?; + let h_a = multiply_edwards(&h_scalar, &a).context("Failed to multiply H*A")?; + let r_prime = subtract_edwards(&s_b, &h_a).context("Failed to subtract HA from SB")?; + Ok(r_prime == r) +} diff --git a/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/utils/mod.rs b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/utils/mod.rs new file mode 100644 index 0000000..da1d6fe --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/programs/balance-payment/src/utils/mod.rs @@ -0,0 +1,3 @@ +pub mod ed25519; + +pub use ed25519::*; diff --git a/dephy-vending_machine-examples/balance-payment/scripts/cli.ts b/dephy-vending_machine-examples/balance-payment/scripts/cli.ts new file mode 100644 index 0000000..1d27fee --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/scripts/cli.ts @@ -0,0 +1,354 @@ +import * as anchor from "@coral-xyz/anchor"; +import * as ed from "@noble/ed25519"; +import { web3, Program, BN } from "@coral-xyz/anchor"; +import { BalancePayment } from "../target/types/balance_payment"; +import { Command } from "commander"; +import { Keypair } from "@solana/web3.js"; +import { v4 as uuidv4 } from "uuid"; +import keccak from "keccak"; +import { readFileSync } from "fs"; +import bs58 from "bs58"; +import os from "os"; +import path from "path"; + +const SIGN_MESSAGE_PREFIX = "DePHY vending machine/Example:\n"; + +const cli = new Command(); + +let provider: anchor.AnchorProvider; +const getBalancePaymentProgram = () => { + provider = anchor.AnchorProvider.env(); + anchor.setProvider(provider); + return anchor.workspace.BalancePayment as Program; +}; + +type Methods = anchor.Program["methods"]; + +const execute = async (tx: ReturnType) => { + const pubkeys = await tx.pubkeys(); + for (const [name, key] of Object.entries(pubkeys)) { + console.log(name, key.toBase58()); + } + const signature = await tx.rpc(); + console.log("signature", signature); + return { signature, pubkeys }; +}; + +const sol = (n: number | string) => { + return new BN(Number(n) * web3.LAMPORTS_PER_SOL); +}; + +const showObj = ( + obj: { [_: string]: web3.PublicKey | BN | any }, + indent = 0 +) => { + const padding = " ".repeat(indent); + for (const [k, v] of Object.entries(obj)) { + if (BN.isBN(v)) { + console.log(padding, k, v.toNumber()); + } else if (v?.toBase58) { + console.log(padding, k, v.toBase58()); + } else if (v && typeof v === "object") { + console.log(padding, k); + showObj(v, indent + 2); + } else { + console.log(padding, k, v); + } + } +}; + +const getUserKeypair = (keypairPath?: string): Keypair => { + // Default path: ~/.config/solana/id.json + const defaultPath = path.join(os.homedir(), ".config", "solana", "id.json"); + const resolvedPath = keypairPath || defaultPath; + + try { + const keypairFile = readFileSync(resolvedPath, "utf-8"); + const keypair = Keypair.fromSecretKey(Buffer.from(JSON.parse(keypairFile))); + return keypair; + } catch (error) { + throw new Error( + `Failed to load keypair from ${resolvedPath}: ${error.message}` + ); + } +}; + +const generate64ByteUUIDPayload = (): Buffer => { + const uuid = uuidv4().replace(/-/g, ""); + const uuidBuffer = Buffer.from(uuid, "hex"); + const extendedBuffer = Buffer.concat([uuidBuffer, Buffer.alloc(48, 0)]); + return extendedBuffer; +}; + +const getNonce = async (user: web3.PublicKey): Promise => { + const balancePayment = getBalancePaymentProgram(); + const userAccountPubkey = getUserAccountPubkey(user); + const userAccount = await balancePayment.account.userAccount.fetch( + userAccountPubkey + ); + return userAccount.nonce; +}; + +const getUserAccountPubkey = (user: web3.PublicKey) => { + const [userAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("USER"), user.toBuffer()], + anchor.workspace.BalancePayment.programId + ); + return userAccountPubkey; +}; + +cli.name("cli"); + +cli + .command("initialize") + .requiredOption("--authority ", "Pubkey") + .requiredOption("--treasury ", "Pubkey") + .requiredOption("--bot ", "Pubkey") + .action(async (opt) => { + const payfiPool = getBalancePaymentProgram(); + const tx = payfiPool.methods.initialize().accountsPartial({ + authority: new web3.PublicKey(opt.authority), + treasury: new web3.PublicKey(opt.treasury), + bot: new web3.PublicKey(opt.bot), + }); + await execute(tx); + }); + +cli + .command("set_treasury") + .requiredOption("--treasury ", "Pubkey") + .action(async (opt) => { + const balancePayment = getBalancePaymentProgram(); + const authority = provider.publicKey; + const tx = balancePayment.methods.setTreasury().accountsPartial({ + authority, + treasury: new web3.PublicKey(opt.treasury), + }); + await execute(tx); + }); + +cli + .command("set_bot") + .requiredOption("--bot ", "Pubkey") + .action(async (opt) => { + const balancePayment = getBalancePaymentProgram(); + const authority = provider.publicKey; + const tx = balancePayment.methods.setBot().accountsPartial({ + authority, + bot: new web3.PublicKey(opt.bot), + }); + await execute(tx); + }); + +cli.command("register").action(async () => { + const balancePayment = getBalancePaymentProgram(); + const user = provider.publicKey; + const tx = balancePayment.methods.register().accountsPartial({ + user, + }); + await execute(tx); +}); + +cli + .command("deposit") + .requiredOption("--amount ", "Amount in SOL") + .action(async (opt) => { + const balancePayment = getBalancePaymentProgram(); + const user = provider.publicKey; + const amount = sol(opt.amount); + const tx = balancePayment.methods.deposit(amount).accountsPartial({ + user, + }); + await execute(tx); + }); + +cli + .command("withdraw") + .requiredOption("--amount ", "Amount in SOL") + .action(async (opt) => { + const balancePayment = getBalancePaymentProgram(); + const user = provider.publicKey; + const amount = sol(opt.amount); + const tx = balancePayment.methods.withdraw(amount).accountsPartial({ + user, + }); + await execute(tx); + }); + +cli + .command("sign_message") + .requiredOption("--minutes ", "Minutes until deadline") + .option( + "--keypair ", + "Path to keypair file (default: ~/.config/solana/id.json)" + ) + .action(async (opt) => { + // Get user's keypair + const userKeypair = getUserKeypair(opt.keypair); + const user = userKeypair.publicKey; // Use the public key from the provided keypair + + // Log the user who is signing + console.log("Signing user:", user.toBase58()); + + // Get nonce from user account + const nonce = await getNonce(user); + + // Convert minutes to deadline (current timestamp + minutes * 60 seconds) + const currentTimestamp = Math.floor(Date.now() / 1000); + const deadline = new BN(currentTimestamp + Number(opt.minutes) * 60); + + // Generate payload + const payload = generate64ByteUUIDPayload(); + + // Create message + const message = Buffer.concat([ + payload, + nonce.toArrayLike(Buffer, "le", 8), + deadline.toArrayLike(Buffer, "le", 8), + ]); + + // Hash the message and generate digest + const messageHash = keccak("keccak256").update(message).digest(); + const hashedMessageBase58 = bs58.encode(messageHash); + const digest = new TextEncoder().encode(`${SIGN_MESSAGE_PREFIX}${hashedMessageBase58}`); + + // Get user's private key + const privateKey = userKeypair.secretKey.slice(0, 32); // First 32 bytes are the private key + + // Sign the message + const signature = await ed.signAsync(digest, privateKey); + + // Create recoverInfo + const recoverInfo = { + signature: Array.from(signature), + payload: Array.from(payload), + deadline, + }; + + // Output recoverInfo as JSON + const jsonString = JSON.stringify(recoverInfo); + console.log("Recover Info (JSON):", jsonString); + + const base64String = Buffer.from(jsonString).toString("base64"); + console.log("Recover Info (Base64)", base64String); + }); + +cli + .command("lock") + .requiredOption("--user ", "User Pubkey") + .requiredOption("--amount ", "Amount in SOL") + .requiredOption("--recoverInfo ", "Recover Info (Base64)") + .action(async (opt) => { + const balancePayment = getBalancePaymentProgram(); + const user = new web3.PublicKey(opt.user); + const amount = sol(opt.amount); + const recoverInfo = JSON.parse( + Buffer.from(opt.recoverInfo, "base64").toString() + ); + + recoverInfo.signature = Array.from(recoverInfo.signature); + recoverInfo.payload = Array.from(recoverInfo.payload); + recoverInfo.deadline = new BN(recoverInfo.deadline, "hex"); + + const [globalAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("GLOBAL")], + balancePayment.programId + ); + const globalAccount = await balancePayment.account.globalAccount.fetch( + globalAccountPubkey + ); + + const tx = balancePayment.methods + .lock(recoverInfo, amount) + .accountsPartial({ + user, + bot: globalAccount.bot, + }); + await execute(tx); + }); + +cli + .command("settle") + .requiredOption("--user ", "User Pubkey") + .requiredOption("--nonce ", "Nonce") + .requiredOption("--amountToTransfer ", "Amount in SOL") + .action(async (opt) => { + const balancePayment = getBalancePaymentProgram(); + const user = new web3.PublicKey(opt.user); + const nonce = new BN(opt.nonce); + const amountToTransfer = sol(opt.amountToTransfer); + const [globalAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("GLOBAL")], + balancePayment.programId + ); + const globalAccount = await balancePayment.account.globalAccount.fetch( + globalAccountPubkey + ); + const tx = balancePayment.methods + .settle(nonce, amountToTransfer) + .accountsPartial({ + user, + treasury: globalAccount.treasury, + bot: globalAccount.bot, + }); + await execute(tx); + }); + + cli + .command("pay") + .requiredOption("--user ", "User Pubkey") + .requiredOption("--amountToTransfer ", "Amount in SOL") + .requiredOption("--recoverInfo ", "Recover Info (Base64)") + .action(async (opt) => { + const balancePayment = getBalancePaymentProgram(); + const user = new web3.PublicKey(opt.user); + const amountToTransfer = sol(opt.amountToTransfer); + const recoverInfo = JSON.parse( + Buffer.from(opt.recoverInfo, "base64").toString() + ); + + recoverInfo.signature = Array.from(recoverInfo.signature); + recoverInfo.payload = Array.from(recoverInfo.payload); + recoverInfo.deadline = new BN(recoverInfo.deadline, "hex"); + + const [globalAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("GLOBAL")], + balancePayment.programId + ); + const globalAccount = await balancePayment.account.globalAccount.fetch( + globalAccountPubkey + ); + + const tx = balancePayment.methods + .pay(recoverInfo, amountToTransfer) + .accountsPartial({ + user, + treasury: globalAccount.treasury, + bot: globalAccount.bot, + }); + await execute(tx); + }); + +cli.command("show_global").action(async () => { + const balancePayment = getBalancePaymentProgram(); + const [globalAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("GLOBAL")], + balancePayment.programId + ); + const globalAccount = await balancePayment.account.globalAccount.fetch( + globalAccountPubkey + ); + showObj(globalAccount); +}); + +cli.command("show_users").action(async () => { + const balancePayment = getBalancePaymentProgram(); + const allUsers = await balancePayment.account.userAccount.all(); + + allUsers.forEach((user) => { + showObj(user); + console.log("-".repeat(50)); + }); +}); + +cli.parse(); diff --git a/dephy-vending_machine-examples/balance-payment/tests/balance-payment.ts b/dephy-vending_machine-examples/balance-payment/tests/balance-payment.ts new file mode 100644 index 0000000..8d9b009 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/tests/balance-payment.ts @@ -0,0 +1,341 @@ +import * as anchor from "@coral-xyz/anchor"; +import { BN, Program, web3 } from "@coral-xyz/anchor"; +import { v4 as uuidv4 } from "uuid"; +import { BalancePayment } from "../target/types/balance_payment"; +import { assert } from "chai"; +import keccak from "keccak"; +import * as ed from "@noble/ed25519"; +import bs58 from 'bs58'; + +const SIGN_MESSAGE_PREFIX = "DePHY vending machine/Example:\n"; + +const sol = function (n: number) { + return new BN(n * web3.LAMPORTS_PER_SOL); +}; + +describe("balance-payment", () => { + anchor.setProvider(anchor.AnchorProvider.env()); + + const program = anchor.workspace.BalancePayment as Program; + + const authority = web3.Keypair.generate(); + const treasury = web3.Keypair.generate(); + const bot = web3.Keypair.generate(); + + const user = web3.Keypair.generate(); + + const [globalAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("GLOBAL")], + anchor.workspace.BalancePayment.programId + ); + + const getUserAccountPubkey = (user: web3.PublicKey) => { + const [userAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("USER"), user.toBuffer()], + anchor.workspace.BalancePayment.programId + ); + return userAccountPubkey; + }; + + const getUserVaultPubkey = (user: web3.PublicKey) => { + const [vaultPubkey, _] = web3.PublicKey.findProgramAddressSync( + [Buffer.from("VAULT"), user.toBuffer()], + anchor.workspace.BalancePayment.programId + ); + return vaultPubkey; + }; + + const getLockAccountPubkey = (user: web3.PublicKey, nonce: BN) => { + const [lockAccountPubkey, _] = web3.PublicKey.findProgramAddressSync( + [ + Buffer.from("LOCK"), + user.toBuffer(), + nonce.toArrayLike(Buffer, "le", 8), + ], + program.programId + ); + return lockAccountPubkey; + }; + + const generate64ByteUUIDPayload = (): Buffer => { + const uuid = uuidv4().replace(/-/g, ""); // 去掉连字符 + const uuidBuffer = Buffer.from(uuid, "hex"); + + const extendedBuffer = Buffer.concat([uuidBuffer, Buffer.alloc(48, 0)]); + + return extendedBuffer; + }; + const airdrop = async (to: web3.PublicKey, amount: BN) => { + await anchor.Native.system() + .methods.transfer(amount) + .accounts({ to }) + .rpc(); + }; + + before(async () => { + await airdrop(user.publicKey, sol(100)); + }); + + it("initialize", async () => { + const tempTreasury = web3.Keypair.generate().publicKey; + const tempBot = web3.Keypair.generate().publicKey; + const { signature } = await program.methods + .initialize() + .accountsPartial({ + authority: authority.publicKey, + treasury: tempTreasury, + bot: tempBot, + }) + .rpcAndKeys(); + console.log("initialize:", signature); + + const global = await program.account.globalAccount.fetch( + globalAccountPubkey + ); + assert.equal(global.authority.toString(), authority.publicKey.toString()); + assert.equal(global.treasury.toString(), tempTreasury.toString()); + assert.equal(global.bot.toString(), tempBot.toString()); + }); + + it("set treasury", async () => { + const { signature } = await program.methods + .setTreasury() + .accountsPartial({ + authority: authority.publicKey, + treasury: treasury.publicKey, + }) + .signers([authority]) + .rpcAndKeys(); + console.log("set_treasury:", signature); + + const global = await program.account.globalAccount.fetch( + globalAccountPubkey + ); + assert.equal(global.treasury.toString(), treasury.publicKey.toString()); + }); + + it("set bot", async () => { + const { signature } = await program.methods + .setBot() + .accountsPartial({ + authority: authority.publicKey, + bot: bot.publicKey, + }) + .signers([authority]) + .rpcAndKeys(); + console.log("set_bot:", signature); + + const global = await program.account.globalAccount.fetch( + globalAccountPubkey + ); + assert.equal(global.bot.toString(), bot.publicKey.toString()); + }); + + it("register", async () => { + const { signature } = await program.methods + .register() + .accountsPartial({ + user: user.publicKey, + }) + .signers([user]) + .rpcAndKeys(); + console.log("register:", signature); + + const userAccountPubkey = getUserAccountPubkey(user.publicKey); + const userAccount = await program.account.userAccount.fetch( + userAccountPubkey + ); + assert.equal( + userAccount.vault.toString(), + getUserVaultPubkey(user.publicKey).toString() + ); + }); + + it("deposit", async () => { + const amount = sol(11); + + const { signature } = await program.methods + .deposit(amount) + .accountsPartial({ + user: user.publicKey, + }) + .signers([user]) + .rpcAndKeys(); + console.log("deposit:", signature); + + const userVaultPubkey = getUserVaultPubkey(user.publicKey); + const userVaultBalance = await program.provider.connection.getBalance( + userVaultPubkey + ); + + assert(amount.eq(new BN(userVaultBalance))); + }); + + it("withdraw", async () => { + const amount = sol(1); + + const { signature } = await program.methods + .withdraw(amount) + .accountsPartial({ + user: user.publicKey, + }) + .signers([user]) + .rpcAndKeys(); + console.log("withdraw:", signature); + + const userVaultPubkey = getUserVaultPubkey(user.publicKey); + const userVaultBalance = await program.provider.connection.getBalance( + userVaultPubkey + ); + + assert(sol(10).eq(new BN(userVaultBalance))); + }); + + it("lock", async () => { + const amount = sol(10); + + const userAccountPubkey = getUserAccountPubkey(user.publicKey); + + let userAccount = await program.account.userAccount.fetch( + userAccountPubkey + ); + + const nonce = userAccount.nonce; + const payload = generate64ByteUUIDPayload(); + + const deadline = new BN(Date.now() / 1000 + 60 * 30); // 30 minutes later + const message = Buffer.concat([ + payload, + nonce.toArrayLike(Buffer, "le", 8), + deadline.toArrayLike(Buffer, "le", 8), + ]); + + const messageHash = keccak("keccak256").update(message).digest(); + const hashedMessageBase58 = bs58.encode(messageHash); + const digest = new TextEncoder().encode(`${SIGN_MESSAGE_PREFIX}${hashedMessageBase58}`); + + const privateKey = user.secretKey.slice(0, 32); + + const signature = await ed.signAsync(digest, privateKey); + + const recoverInfo = { + signature: Array.from(signature), + payload: Array.from(payload), + deadline, + }; + + const { signature: txSignature } = await program.methods + .lock(recoverInfo, amount) + .accountsPartial({ + user: user.publicKey, + bot: bot.publicKey, + }) + .signers([bot]) + .rpcAndKeys(); + + console.log("lock:", txSignature); + + const lockAccountPubkey = getLockAccountPubkey(user.publicKey, nonce); + const lockAccount = await program.account.lockAccount.fetch( + lockAccountPubkey + ); + assert.equal(lockAccount.amount.toString(), amount.toString()); + + userAccount = await program.account.userAccount.fetch(userAccountPubkey); + assert(userAccount.lockedAmount.eq(amount)); + }); + + it("settle", async () => { + const nonce = new BN(0); + const amountToTransfer = sol(5); + + const { signature } = await program.methods + .settle(nonce, amountToTransfer) + .accountsPartial({ + user: user.publicKey, + treasury: treasury.publicKey, + bot: bot.publicKey, + }) + .signers([bot]) + .rpcAndKeys(); + + console.log("settle:", signature); + + const treasuryBalance = await program.provider.connection.getBalance( + treasury.publicKey + ); + assert.equal(treasuryBalance, amountToTransfer.toNumber()); + + const lockAccountPubkey = getLockAccountPubkey(user.publicKey, nonce); + + try { + await program.account.lockAccount.fetch( + lockAccountPubkey + ); + } catch (error) { + assert(error.message.includes("Account does not exist")) + } + + const userAccountPubkey = getUserAccountPubkey(user.publicKey); + const userAccount = await program.account.userAccount.fetch( + userAccountPubkey + ); + assert(userAccount.lockedAmount.eq(new BN(0))); + }); + + it("pay", async () => { + const amountToTransfer = sol(1); + + const userAccountPubkey = getUserAccountPubkey(user.publicKey); + + let userAccount = await program.account.userAccount.fetch( + userAccountPubkey + ); + + const nonce = userAccount.nonce; + const payload = generate64ByteUUIDPayload(); + + const deadline = new BN(Date.now() / 1000 + 60 * 30); // 30 minutes later + const message = Buffer.concat([ + payload, + nonce.toArrayLike(Buffer, "le", 8), + deadline.toArrayLike(Buffer, "le", 8), + ]); + + const messageHash = keccak("keccak256").update(message).digest(); + const hashedMessageBase58 = bs58.encode(messageHash); + const digest = new TextEncoder().encode(`${SIGN_MESSAGE_PREFIX}${hashedMessageBase58}`); + + const privateKey = user.secretKey.slice(0, 32); + + const signature = await ed.signAsync(digest, privateKey); + + const recoverInfo = { + signature: Array.from(signature), + payload: Array.from(payload), + deadline, + }; + + const vaultBalanceBefore = await program.provider.connection.getBalance( + userAccount.vault + ); + + const { signature: txSignature } = await program.methods + .pay(recoverInfo, amountToTransfer) + .accountsPartial({ + user: user.publicKey, + treasury: treasury.publicKey, + bot: bot.publicKey, + }) + .signers([bot]) + .rpcAndKeys(); + + console.log("pay:", txSignature); + + const vaultBalanceAfter = await program.provider.connection.getBalance( + userAccount.vault + ); + + assert.equal(vaultBalanceBefore - vaultBalanceAfter, amountToTransfer.toNumber()); + }); +}); diff --git a/dephy-vending_machine-examples/balance-payment/tsconfig.json b/dephy-vending_machine-examples/balance-payment/tsconfig.json new file mode 100644 index 0000000..247d160 --- /dev/null +++ b/dephy-vending_machine-examples/balance-payment/tsconfig.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "types": ["mocha", "chai"], + "typeRoots": ["./node_modules/@types"], + "lib": ["es2015"], + "module": "commonjs", + "target": "es6", + "esModuleInterop": true, + "resolveJsonModule": true + } +} diff --git a/dephy-vending_machine-examples/cliff.toml b/dephy-vending_machine-examples/cliff.toml new file mode 100644 index 0000000..cfd438c --- /dev/null +++ b/dephy-vending_machine-examples/cliff.toml @@ -0,0 +1,95 @@ +# git-cliff ~ configuration file +# https://git-cliff.org/docs/configuration + +[changelog] +# changelog header +header = """ +# Changelog\n +All notable changes to this project will be documented in this file. See [conventional commits](https://www.conventionalcommits.org/) for commit guidelines.\n +""" +# template for the changelog body +# https://keats.github.io/tera/docs/#introduction +body = """ +--- +{% if version %}\ + {% if previous.version %}\ + ## [{{ version | trim_start_matches(pat="v") }}]($REPO/compare/{{ previous.version }}..{{ version }}) - {{ timestamp | date(format="%Y-%m-%d") }} + {% else %}\ + ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} + {% endif %}\ +{% else %}\ + ## [unreleased] +{% endif %}\ +{% for group, commits in commits | group_by(attribute="group") %} + ### {{ group | striptags | trim | upper_first }} + {% for commit in commits + | filter(attribute="scope") + | sort(attribute="scope") %} + - **({{commit.scope}})**{% if commit.breaking %} [**breaking**]{% endif %} \ + {{ commit.message|trim }} - ([{{ commit.id | truncate(length=7, end="") }}]($REPO/commit/{{ commit.id }})) - {{ commit.author.name }} + {%- endfor -%} + {% raw %}\n{% endraw %}\ + {%- for commit in commits %} + {%- if commit.scope -%} + {% else -%} + - {% if commit.breaking %} [**breaking**]{% endif %}\ + {{ commit.message|trim }} - ([{{ commit.id | truncate(length=7, end="") }}]($REPO/commit/{{ commit.id }})) - {{ commit.author.name }} + {% endif -%} + {% endfor -%} +{% endfor %}\n +""" +# template for the changelog footer +footer = """ + +""" +# remove the leading and trailing whitespace from the templates +trim = true +# postprocessors +postprocessors = [ + { pattern = '\$REPO', replace = "https://github.com/dephy-io/dephy-vending_machine-examples" }, # replace repository URL +] + +[git] +# parse the commits based on https://www.conventionalcommits.org +conventional_commits = true +# filter out the commits that are not conventional +filter_unconventional = false +# process each line of a commit as an individual commit +split_commits = false +# regex for preprocessing the commit messages +commit_preprocessors = [ + # { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/orhun/git-cliff/issues/${2}))"}, # replace issue numbers +] +# regex for parsing and grouping commits +commit_parsers = [ + { message = "\\[skip", skip = true }, + { message = "\\p{Han}", skip = true }, + { message = "^feat", group = "Features" }, + { message = "^fix", group = "Bug Fixes" }, + { message = "^doc", group = "Documentation" }, + { message = "^perf", group = "Performance" }, + { message = "^refactor", group = "Refactoring" }, + { message = "^style", group = "Style" }, + { message = "^revert", group = "Revert" }, + { message = "^test", group = "Tests" }, + { message = "^chore\\(version\\):", skip = true }, + { message = "^chore", group = "Miscellaneous Chores" }, + { message = ".*", group = "Other" }, + { body = ".*security", group = "Security" }, +] +# protect breaking changes from being skipped due to matching a skipping commit_parser +protect_breaking_commits = false +# filter out the commits that are not matched by commit parsers +filter_commits = false +# regex for matching git tags +tag_pattern = "v[0-9].*" +# regex for skipping tags +skip_tags = "v0.1.0-beta.1" +# regex for ignoring tags +ignore_tags = "" +# sort the tags topologically +topo_order = false +# sort the commits inside sections by oldest/newest order +sort_commits = "oldest" +# limit the number of commits included in the changelog. +# limit_commits = 42 diff --git a/dephy-vending_machine-examples/deny.toml b/dephy-vending_machine-examples/deny.toml new file mode 100644 index 0000000..36e879a --- /dev/null +++ b/dephy-vending_machine-examples/deny.toml @@ -0,0 +1,58 @@ +[advisories] +version = 2 +yanked = "warn" +db-path = "~/.cargo/advisory-db" +db-urls = ["https://github.com/rustsec/advisory-db"] +ignore = [ + # waiting for nostr crates to be updated + "RUSTSEC-2024-0384", + # waiting for solana crates to be updated + "RUSTSEC-2022-0093", + # waiting for solana crates to be updated + "RUSTSEC-2024-0388", + # waiting for solana crates to be updated + "RUSTSEC-2024-0344", + # waiting for solana crates to be updated + "RUSTSEC-2021-0145", + # waiting for solana crates to be updated + "RUSTSEC-2024-0375", +] + +[bans] +multiple-versions = "warn" +wildcards = "deny" +highlight = "all" + +[licenses] +version = 2 +confidence-threshold = 0.8 + +allow = [ + "MIT", + "MITNFA", + "Apache-2.0", + "Apache-2.0 WITH LLVM-exception", + "BSD-3-Clause", + "BSD-2-Clause", + "0BSD", + "ISC", + "Unicode-3.0", + "Unicode-DFS-2016", + "Unlicense", + "MPL-2.0", + "CC0-1.0", + "Zlib", + # https://github.com/briansmith/ring/issues/902 + "LicenseRef-ring", +] + +[[licenses.clarify]] +name = "ring" +expression = "LicenseRef-ring" +license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }] + +[sources] +unknown-registry = "deny" +unknown-git = "deny" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +allow-git = ["git://github.com/anza-xyz/agave.git"] diff --git a/dephy-vending_machine-examples/doc/architecture.png b/dephy-vending_machine-examples/doc/architecture.png new file mode 100644 index 0000000..f102438 Binary files /dev/null and b/dephy-vending_machine-examples/doc/architecture.png differ diff --git a/dephy-vending_machine-examples/docker-compose-postgres-init/decharge-controller-docker-entrypoint-initdb.d/migrate.sh b/dephy-vending_machine-examples/docker-compose-postgres-init/decharge-controller-docker-entrypoint-initdb.d/migrate.sh new file mode 100755 index 0000000..d33b873 --- /dev/null +++ b/dephy-vending_machine-examples/docker-compose-postgres-init/decharge-controller-docker-entrypoint-initdb.d/migrate.sh @@ -0,0 +1,17 @@ +#!/bin/bash +set -e + +export PGPASSWORD="dephy" + +psql -U dephy -c "CREATE DATABASE dephy_messaging_network;" +psql -U dephy -c "CREATE DATABASE dephy_decharge_controller_server;" + +for sql_file in /messaging_network_migrations/*.sql; do + echo "Executing $sql_file..." + psql -U dephy -d dephy_messaging_network -f "$sql_file" +done + +for sql_file in /decharge_controller_server_migrations/*.sql; do + echo "Executing $sql_file..." + psql -U dephy -d dephy_decharge_controller_server -f "$sql_file" +done diff --git a/dephy-vending_machine-examples/docker-compose-postgres-init/messaging_network_migrations/20241125030333_initial.sql b/dephy-vending_machine-examples/docker-compose-postgres-init/messaging_network_migrations/20241125030333_initial.sql new file mode 100644 index 0000000..b2acaca --- /dev/null +++ b/dephy-vending_machine-examples/docker-compose-postgres-init/messaging_network_migrations/20241125030333_initial.sql @@ -0,0 +1,16 @@ +CREATE TABLE IF NOT EXISTS events ( + id bigserial PRIMARY KEY, + event_id character varying NOT NULL, + prev_event_id character varying NOT NULL, + pubkey character varying NOT NULL, + created_at bigint NOT NULL, + original character varying NOT NULL, + "session" character varying NOT NULL, + mention character varying, + + CONSTRAINT events_unique_event_id + UNIQUE (event_id), + + CONSTRAINT events_unique_pubkey_session_prev_event_id + UNIQUE (pubkey, session, prev_event_id) +); diff --git a/dephy-vending_machine-examples/docker-compose.yml b/dephy-vending_machine-examples/docker-compose.yml new file mode 100644 index 0000000..1660dfa --- /dev/null +++ b/dephy-vending_machine-examples/docker-compose.yml @@ -0,0 +1,85 @@ +services: + postgres: + image: postgres:16 + restart: always + environment: + POSTGRES_USER: dephy + POSTGRES_PASSWORD: dephy + volumes: + - postgres_data:/var/lib/postgresql/data + - ./docker-compose-postgres-init/messaging_network_migrations:/messaging_network_migrations + - ./docker-compose-postgres-init/decharge-controller-docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d + - ./examples/decharge-controller/migrations:/decharge_controller_server_migrations + ports: + - "6432:5432" + + dephy-messaging-network: + depends_on: + - postgres + image: dephyio/dephy-messaging-network:master + restart: always + environment: + RUST_LOG: "info,dephy_messaging_network=debug" + RUST_BACKTRACE: "1" + command: "serve --pg-url 'postgresql://dephy:dephy@postgres:5432/dephy_messaging_network' --api-addr 0.0.0.0:8000" + ports: + - "8000:8000" + + dephy-decharge-controller-server: + depends_on: + - dephy-messaging-network + image: dephyio/dephy-vending-machine-examples:main + restart: always + entrypoint: /usr/bin/dephy-decharge-controller-server + environment: + RUST_LOG: "debug" + RUST_BACKTRACE: "1" + volumes: + - ./keypairs/bot.demo.json:/opt/dephy-vending-machine-examples/data/solana-keypair + command: > + --nostr-relay 'ws://dephy-messaging-network:8000' + --key '80ed9975bc5c18c8852c202e4ddc0ae62abf7d9484c3a0d425f501623907129b' + --solana-rpc-url "${SOLANA_RPC_URL:-http://host.docker.internal:8899}" + --pg-url 'postgresql://dephy:dephy@postgres:5432/dephy_decharge_controller_server' + + dephy-decharge-controller-node-1: + depends_on: + - dephy-messaging-network + image: dephyio/dephy-vending-machine-examples:main + restart: always + entrypoint: /usr/bin/dephy-decharge-controller-node + user: root # have to be root to write key file to data directory + environment: + RUST_LOG: "debug" + RUST_BACKTRACE: "1" + volumes: + - dephy_decharge_controller_node_1_data:/opt/dephy-vending-machine-examples/data:rw + command: > + --nostr-relay 'ws://dephy-messaging-network:8000' + --solana-rpc-url "${SOLANA_RPC_URL:-http://host.docker.internal:8899}" + --machine-pubkeys 'd041ea9854f2117b82452457c4e6d6593a96524027cd4032d2f40046deb78d93' + --admin-pubkey '90b6bb6472b2609c63dfb588aa1a10780dc043ffc0ab2349679c50644c0bc445' + + dephy-gacha-controller: + depends_on: + - dephy-messaging-network + image: dephyio/dephy-vending-machine-examples:main + restart: always + entrypoint: /usr/bin/dephy-gacha-controller + user: root # have to be root to write key file to data directory + environment: + RUST_LOG: "debug" + RUST_BACKTRACE: "1" + volumes: + - dephy_gacha_controller_data:/opt/dephy-vending-machine-examples/data:rw + - ./keypairs/bot.demo.json:/opt/dephy-vending-machine-examples/data/solana-keypair + command: > + --nostr-relay 'ws://dephy-messaging-network:8000' + --solana-rpc-url "${SOLANA_RPC_URL:-http://host.docker.internal:8899}" + --machine-pubkeys 'd041ea9854f2117b82452457c4e6d6593a96524027cd4032d2f40046deb78d93' + --admin-pubkey 'd041ea9854f2117b82452457c4e6d6593a96524027cd4032d2f40046deb78d93' + +volumes: + postgres_data: + dephy_decharge_controller_node_1_data: + dephy_gacha_controller_data: diff --git a/dephy-vending_machine-examples/examples/decharge-controller/Cargo.toml b/dephy-vending_machine-examples/examples/decharge-controller/Cargo.toml new file mode 100644 index 0000000..7e0bbab --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "dephy-decharge-controller" +version = "0.1.0" +edition = "2021" +license.workspace = true + +[dependencies] +clap = { workspace = true } +dephy-balance-payment-sdk = { workspace = true } +futures = { workspace = true } +nostr = { workspace = true } +nostr-sdk = { workspace = true } +sea-query = "0.32.1" +sea-query-binder = { version = "0.7.0", features = ["runtime-tokio", "sqlx-postgres"] } +serde = { workspace = true } +serde_json = { workspace = true } +sqlx = { version = "0.8.3", features = ["postgres", "runtime-tokio"] } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["process", "rt-multi-thread"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } + +[[bin]] +name = "dephy-decharge-controller-node" +path = "bin/dephy-decharge-controller-node.rs" + +[[bin]] +name = "dephy-decharge-controller-server" +path = "bin/dephy-decharge-controller-server.rs" diff --git a/dephy-vending_machine-examples/examples/decharge-controller/README.md b/dephy-vending_machine-examples/examples/decharge-controller/README.md new file mode 100644 index 0000000..a153c50 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/README.md @@ -0,0 +1,84 @@ +# dephy-decharge-controller + +## Run by Docker Compose + +```bash +docker compose up +``` + +## Run manually + +### Prepare + +In this example, you should have a messaging network running on `ws://127.0.0.1:8000`. +You can modify `--nostr-relay` if it is running on a different address. + +To run a messaging network you need a postgresql database with schema: + +```sql +CREATE TABLE IF NOT EXISTS events ( + id bigserial PRIMARY KEY, + event_id character varying NOT NULL, + prev_event_id character varying NOT NULL, + pubkey character varying NOT NULL, + created_at bigint NOT NULL, + original character varying NOT NULL, + "session" character varying NOT NULL, + mention character varying, + + CONSTRAINT events_unique_event_id + UNIQUE (event_id), + + CONSTRAINT events_unique_pubkey_session_prev_event_id + UNIQUE (pubkey, session, prev_event_id) +); +``` + +To run a messaging network by docker: + +```shell +docker run --name dephy-messaging-network --restart=always --network="host" -d dephyio/dephy-messaging-network:master serve --pg-url 'postgresql://:@
/' +``` + +### Run Server + +The schema of the database is in [migrations](./migrations/). + +You can migrate it by [sqlx-cli](https://crates.io/crates/sqlx-cli) or enable those sql manually. To migrate it by sqlx-cli: + +```shell +sqlx database create --database-url postgresql://>@
/ +sqlx migrate run --database-url postgresql://:@
/ +``` + +The server need your solana keypair. + +```shell +mkdir data +# copy your keypair to data/solana-keypair +``` + +To run the server: + +```shell +cargo run --bin dephy-decharge-controller-server -- --nostr-relay ws://127.0.0.1:8000 --key --pg-url postgresql://:@
/ +``` + +### Run Node (this is on charger equipment side) + +The node need your solana keypair. + +```shell +mkdir data +# copy your keypair to data/solana-keypair +``` + +```shell +cargo run --bin dephy-decharge-controller-node -- --nostr-relay ws://127.0.0.1:8000 --machine-pubkeys d041ea9854f2117b82452457c4e6d6593a96524027cd4032d2f40046deb78d93 --admin-pubkey +``` + +### Cli Example (it simulates a charging process) + +```shell +cargo run --example cli -- --nostr-relay ws://127.0.0.1:8000 --machine-pubkey d041ea9854f2117b82452457c4e6d6593a96524027cd4032d2f40046deb78d93 --user --nonce --recover-info +``` diff --git a/dephy-vending_machine-examples/examples/decharge-controller/bin/dephy-decharge-controller-node.rs b/dephy-vending_machine-examples/examples/decharge-controller/bin/dephy-decharge-controller-node.rs new file mode 100644 index 0000000..9152019 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/bin/dephy-decharge-controller-node.rs @@ -0,0 +1,128 @@ +use std::path::PathBuf; + +use clap::value_parser; +use clap::Arg; +use clap::ArgAction; +use clap::ArgMatches; +use clap::Command; +use nostr::Keys; + +const SESSION: &str = "dephy-decharge-controller"; + +fn parse_args() -> Command { + Command::new("dephy-decharge-controller-node") + .arg_required_else_help(true) + .about("Dephy decharge controller node daemon") + .version(dephy_decharge_controller::VERSION) + .arg( + Arg::new("NOSTR_RELAY") + .long("nostr-relay") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Nostr relay address"), + ) + .arg( + Arg::new("KEY_FILE") + .long("key-file") + .num_args(1) + .default_value("data/key") + .value_parser(value_parser!(PathBuf)) + .action(ArgAction::Set) + .help("Path to the file containing the hex or bech32 secret key"), + ) + .arg( + Arg::new("ADMIN_PUBKEY") + .long("admin-pubkey") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Admin public key"), + ) + .arg( + Arg::new("MACHINE_PUBKEYS") + .long("machine-pubkeys") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Machine public keys, comma separated"), + ) + .arg( + Arg::new("SOLANA_RPC_URL") + .long("solana-rpc-url") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Solana RPC URL"), + ) +} + +async fn controller(args: &ArgMatches) { + let nostr_relay = args.get_one::("NOSTR_RELAY").unwrap(); + let key_file_path = args.get_one::("KEY_FILE").unwrap(); + let keys = read_or_generate_keypair(key_file_path); + let admin_pubkey = args + .get_one::("ADMIN_PUBKEY") + .unwrap() + .parse() + .expect("Invalid admin pubkey"); + let machine_pubkeys = args + .get_one::("MACHINE_PUBKEYS") + .unwrap() + .split(',') + .map(|s| s.parse().expect("Invalid machine pubkey")) + .collect(); + let solana_rpc_url = args.get_one::("SOLANA_RPC_URL").unwrap(); + + println!("nostr relay: {}", nostr_relay); + println!("pubkey: {}", keys.public_key()); + + let client = dephy_decharge_controller::RelayClient::new(nostr_relay, &keys, SESSION, 4096) + .await + .expect("Failed to connect to relay"); + + let message_handler = dephy_decharge_controller::node::MessageHandler::new( + client, + keys.public_key(), + admin_pubkey, + machine_pubkeys, + solana_rpc_url, + ); + + message_handler.run().await +} + +fn read_or_generate_keypair(path: &PathBuf) -> Keys { + let keys = std::fs::read_to_string(path) + .map(|content| content.trim().parse().expect("Invalid key")) + .unwrap_or_else(|_| { + tracing::info!( + "Key file not found, generating a new one at: {}", + path.display() + ); + let keys = Keys::generate(); + std::fs::write(path, keys.secret_key().to_secret_hex()) + .unwrap_or_else(|e| panic!("Failed to write key {}: {e:?}", path.display())); + keys + }); + + let pubkey_path = path.with_extension("pub"); + std::fs::write(&pubkey_path, keys.public_key().to_hex()).unwrap_or_else(|e| { + panic!( + "Failed to write public key {}: {e:?}", + pubkey_path.display() + ) + }); + + keys +} + +#[tokio::main] +async fn main() { + let _ = tracing_subscriber::fmt() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .try_init(); + + let cmd = parse_args(); + controller(&cmd.get_matches()).await; +} diff --git a/dephy-vending_machine-examples/examples/decharge-controller/bin/dephy-decharge-controller-server.rs b/dephy-vending_machine-examples/examples/decharge-controller/bin/dephy-decharge-controller-server.rs new file mode 100644 index 0000000..6f82760 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/bin/dephy-decharge-controller-server.rs @@ -0,0 +1,110 @@ +use std::path::PathBuf; + +use clap::value_parser; +use clap::Arg; +use clap::ArgAction; +use clap::ArgMatches; +use clap::Command; +use nostr::Keys; + +const SESSION: &str = "dephy-decharge-controller"; + +fn parse_args() -> Command { + Command::new("dephy-decharge-controller-server") + .arg_required_else_help(true) + .about("Dephy decharge controller server") + .version(dephy_decharge_controller::VERSION) + .arg( + Arg::new("NOSTR_RELAY") + .long("nostr-relay") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Nostr relay address"), + ) + .arg( + Arg::new("KEY") + .long("key") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Hex or bech32 secret key"), + ) + .arg( + Arg::new("PG_URL") + .long("pg-url") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Will use this address to connect to postgres"), + ) + .arg( + Arg::new("SOLANA_RPC_URL") + .long("solana-rpc-url") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Solana RPC URL"), + ) + .arg( + Arg::new("SOLANA_KEYPAIR") + .long("solana-keypair") + .num_args(1) + .default_value("data/solana-keypair") + .value_parser(value_parser!(PathBuf)) + .action(ArgAction::Set) + .help("Solana keypair path"), + ) +} + +async fn controller(args: &ArgMatches) { + let nostr_relay = args.get_one::("NOSTR_RELAY").unwrap(); + let keys: Keys = args + .get_one::("KEY") + .unwrap() + .parse() + .expect("Invalid key"); + let pg_url = args.get_one::("PG_URL").unwrap(); + let solana_rpc_url = args.get_one::("SOLANA_RPC_URL").unwrap(); + let solana_keypair_path = args.get_one::("SOLANA_KEYPAIR").unwrap(); + if !solana_keypair_path.exists() { + panic!( + "Solana keypair file not found: {}", + solana_keypair_path.display() + ); + } + + println!("nostr relay: {}", nostr_relay); + println!("pubkey: {}", keys.public_key()); + + let client = dephy_decharge_controller::RelayClient::new(nostr_relay, &keys, SESSION, 4096) + .await + .expect("Failed to connect to relay"); + + let db = sqlx::PgPool::connect(pg_url) + .await + .expect("Failed to connect to database"); + let state = dephy_decharge_controller::server::State::new(db); + + let message_handler = dephy_decharge_controller::server::MessageHandler::new( + client, + state, + solana_rpc_url, + solana_keypair_path + .to_str() + .expect("Invalid solana keypair path"), + None, + ); + + message_handler.run().await +} + +#[tokio::main] +async fn main() { + let _ = tracing_subscriber::fmt() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .try_init(); + + let cmd = parse_args(); + controller(&cmd.get_matches()).await; +} diff --git a/dephy-vending_machine-examples/examples/decharge-controller/examples/cli.rs b/dephy-vending_machine-examples/examples/decharge-controller/examples/cli.rs new file mode 100644 index 0000000..a251027 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/examples/cli.rs @@ -0,0 +1,158 @@ +use std::path::PathBuf; + +use clap::value_parser; +use clap::Arg; +use clap::ArgAction; +use clap::ArgMatches; +use clap::Command; +use dephy_decharge_controller::message::DephyDechargeMessage; +use dephy_decharge_controller::message::DephyDechargeMessageRequestPayload; +use dephy_decharge_controller::message::DephyDechargeStatus; +use dephy_decharge_controller::message::DephyDechargeStatusReason; +use nostr::Keys; +use nostr::Timestamp; +use nostr_sdk::EventId; + +const SESSION: &str = "dephy-decharge-controller"; + +fn parse_args() -> Command { + Command::new("dephy-decharge-controller-cli") + .arg_required_else_help(true) + .about("Dephy decharge controller") + .version(dephy_decharge_controller::VERSION) + .arg( + Arg::new("NOSTR_RELAY") + .long("nostr-relay") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Nostr relay address"), + ) + .arg( + Arg::new("KEY_FILE") + .long("key-file") + .num_args(1) + .default_value("data/key") + .value_parser(value_parser!(PathBuf)) + .action(ArgAction::Set) + .help("Path to the file containing the hex or bech32 secret key"), + ) + .arg( + Arg::new("MACHINE_PUBKEY") + .long("machine-pubkey") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Machine public keys, comma separated"), + ) + .arg( + Arg::new("user") + .long("user") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("User public key"), + ) + .arg( + Arg::new("nonce") + .long("nonce") + .num_args(1) + .required(true) + .value_parser(value_parser!(u64)) + .action(ArgAction::Set) + .help("Nonce"), + ) + .arg( + Arg::new("recover_info") + .long("recover-info") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Recover info"), + ) +} + +async fn cli(args: &ArgMatches) { + let nostr_relay = args.get_one::("NOSTR_RELAY").unwrap(); + let key_file_path = args.get_one::("KEY_FILE").unwrap(); + let keys = read_or_generate_keypair(key_file_path); + let machine_pubkey = args + .get_one::("MACHINE_PUBKEY") + .unwrap() + .parse() + .expect("Invalid machine pubkey"); + let user = args.get_one::("user").unwrap(); + let nonce = args.get_one::("nonce").unwrap(); + let recover_info = args.get_one::("recover_info").unwrap(); + + let client = dephy_decharge_controller::RelayClient::new(nostr_relay, &keys, SESSION, 4096) + .await + .expect("Failed to connect to relay"); + + let mut notifications = client.notifications(); + client + .subscribe(Timestamp::now(), [machine_pubkey]) + .await + .expect("Failed to subscribe"); + + let handler = tokio::spawn(async move { + loop { + let notification = notifications.recv().await; + tracing::info!("Received notification: {:?}", notification); + } + }); + + let payload = serde_json::to_string(&DephyDechargeMessageRequestPayload { + user: user.clone(), + nonce: *nonce, + recover_info: recover_info.clone(), + }) + .expect("Failed to serialize payload"); + + client + .send_event(&machine_pubkey.to_hex(), &DephyDechargeMessage::Request { + to_status: DephyDechargeStatus::Working, + reason: DephyDechargeStatusReason::UserRequest, + initial_request: EventId::all_zeros(), + payload, + }) + .await + .expect("Failed to send event"); + + handler.await.expect("Notification handler failed"); +} + +fn read_or_generate_keypair(path: &PathBuf) -> Keys { + let keys = std::fs::read_to_string(path) + .map(|content| content.trim().parse().expect("Invalid key")) + .unwrap_or_else(|_| { + tracing::info!( + "Key file not found, generating a new one at: {}", + path.display() + ); + let keys = Keys::generate(); + std::fs::write(path, keys.secret_key().to_secret_hex()) + .unwrap_or_else(|e| panic!("Failed to write key {}: {e:?}", path.display())); + keys + }); + + let pubkey_path = path.with_extension("pub"); + std::fs::write(&pubkey_path, keys.public_key().to_hex()).unwrap_or_else(|e| { + panic!( + "Failed to write public key {}: {e:?}", + pubkey_path.display() + ) + }); + + keys +} + +#[tokio::main] +async fn main() { + let _ = tracing_subscriber::fmt() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .try_init(); + + let cmd = parse_args(); + cli(&cmd.get_matches()).await; +} diff --git a/dephy-vending_machine-examples/examples/decharge-controller/migrations/20250116011256_initial.sql b/dephy-vending_machine-examples/examples/decharge-controller/migrations/20250116011256_initial.sql new file mode 100644 index 0000000..ef2a043 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/migrations/20250116011256_initial.sql @@ -0,0 +1,6 @@ +CREATE TABLE IF NOT EXISTS received_events ( + id bigserial PRIMARY KEY, + event_id character varying NOT NULL, + created_at bigint NOT NULL, + is_processed boolean NOT NULL +); diff --git a/dephy-vending_machine-examples/examples/decharge-controller/src/lib.rs b/dephy-vending_machine-examples/examples/decharge-controller/src/lib.rs new file mode 100644 index 0000000..2da85c3 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/src/lib.rs @@ -0,0 +1,9 @@ +pub mod message; +pub mod node; +mod relay_client; +pub mod server; + +/// dephy-decharge-controller version +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); + +pub use relay_client::RelayClient; diff --git a/dephy-vending_machine-examples/examples/decharge-controller/src/message.rs b/dephy-vending_machine-examples/examples/decharge-controller/src/message.rs new file mode 100644 index 0000000..5548275 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/src/message.rs @@ -0,0 +1,50 @@ +use nostr::EventId; +use serde::Deserialize; +use serde::Serialize; + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[repr(u8)] +pub enum DephyDechargeStatus { + Available = 1, + Working = 2, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[repr(u8)] +pub enum DephyDechargeStatusReason { + UserRequest = 1, + AdminRequest = 2, + UserBehaviour = 3, + LockFailed = 5, + Reset = 4, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum DephyDechargeMessage { + Request { + to_status: DephyDechargeStatus, + reason: DephyDechargeStatusReason, + initial_request: EventId, + payload: String, + }, + Status { + status: DephyDechargeStatus, + reason: DephyDechargeStatusReason, + initial_request: EventId, + payload: String, + }, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DephyDechargeMessageRequestPayload { + pub user: String, + pub nonce: u64, + pub recover_info: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DephyDechargeMessageStatusPayload { + pub user: String, + pub nonce: u64, + pub recover_info: String, +} diff --git a/dephy-vending_machine-examples/examples/decharge-controller/src/node/message_handler.rs b/dephy-vending_machine-examples/examples/decharge-controller/src/node/message_handler.rs new file mode 100644 index 0000000..db134f6 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/src/node/message_handler.rs @@ -0,0 +1,390 @@ +use std::collections::HashMap; +use std::collections::HashSet; + +use nostr::Event; +use nostr::EventId; +use nostr::PublicKey; +use nostr::RelayMessage; +use nostr::Timestamp; +use nostr_sdk::RelayPoolNotification; + +use crate::message::DephyDechargeMessage; +use crate::message::DephyDechargeMessageRequestPayload; +use crate::message::DephyDechargeMessageStatusPayload; +use crate::message::DephyDechargeStatus; +use crate::message::DephyDechargeStatusReason; +use crate::relay_client::extract_mention; +use crate::RelayClient; + +const PREPAID_AMOUNT: u64 = 10_000_000; + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("Serde json error: {0}")] + SerdeJson(#[from] serde_json::Error), + #[error("Nostr key error: {0}")] + NostrKey(#[from] nostr::key::Error), + #[error("Relay client error: {0}")] + RelayClient(#[from] crate::relay_client::Error), + #[error("Machine not mentioned in event: {0:?}")] + MachineNotMentioned(Event), + #[error("The machine mentioned by event is not controlled by us: {0:?}")] + MachineNotControlled(Event), + #[error("Only support status event when update machine, but got: {0:?}")] + OnlySupportStatusEventWhenUpdateMachine(Event), +} + +pub struct Machine { + #[allow(dead_code)] + pubkey: PublicKey, + status: DephyDechargeStatus, + initial_request: Option, +} + +pub struct MessageHandler { + client: RelayClient, + controller_pubkey: PublicKey, + admin_pubkey: PublicKey, + machines: HashMap, + started_at: Timestamp, + solana_rpc_url: String, +} + +impl MessageHandler { + pub fn new( + client: RelayClient, + controller_pubkey: PublicKey, + admin_pubkey: PublicKey, + machine_pubkeys: HashSet, + solana_rpc_url: &str, + ) -> Self { + let started_at = Timestamp::now(); + let machines = machine_pubkeys + .into_iter() + .map(|pubkey| { + (pubkey, Machine { + pubkey, + status: DephyDechargeStatus::Available, + initial_request: None, + }) + }) + .collect(); + + Self { + client, + controller_pubkey, + admin_pubkey, + machines, + started_at, + solana_rpc_url: solana_rpc_url.to_string(), + } + } + + pub async fn update_machine(&mut self, event: &Event) -> Result<(), Error> { + let mention = PublicKey::parse( + extract_mention(event).ok_or_else(|| Error::MachineNotMentioned(event.clone()))?, + )?; + + let machine = self + .machines + .get_mut(&mention) + .ok_or_else(|| Error::MachineNotControlled(event.clone()))?; + + let message = serde_json::from_str::(&event.content)?; + + match message { + DephyDechargeMessage::Request { .. } => { + return Err(Error::OnlySupportStatusEventWhenUpdateMachine( + event.clone(), + )) + } + + DephyDechargeMessage::Status { + status, + initial_request, + .. + } => { + machine.status = status; + machine.initial_request = Some(initial_request); + } + } + + Ok(()) + } + + pub async fn run(mut self) { + let mut notifications = self.client.notifications(); + + let checking_client = self.client.clone(); + let relay_checker = async move { + checking_client + .run_relay_checker(std::time::Duration::from_secs(10)) + .await + }; + + let message_handler = async move { + let mut sub_ids = HashMap::new(); + + for machine_pubkey in self.machines.keys().copied() { + let sub_id = self + .client + .subscribe_last_event( + self.started_at, + Some(&self.controller_pubkey), + &machine_pubkey, + ) + .await + .expect("Failed to subscribe events"); + + sub_ids.insert(sub_id, machine_pubkey); + } + + while !sub_ids.is_empty() { + let notification = notifications + .recv() + .await + .expect("Failed to receive notification"); + tracing::debug!("Received notification: {:?}", notification); + + match notification { + RelayPoolNotification::Shutdown => panic!("Relay pool shutdown"), + + RelayPoolNotification::Message { + message: + RelayMessage::Closed { + message, + subscription_id, + }, + .. + } => { + if sub_ids.contains_key(&subscription_id) { + tracing::error!( + "Subscription closed before EndOfStoredEvents: {}", + message + ); + panic!("Subscription closed before EndOfStoredEvents: {message}"); + } + } + + RelayPoolNotification::Message { + message: RelayMessage::EndOfStoredEvents(subscription_id), + .. + } => { + sub_ids.remove(&subscription_id); + } + + RelayPoolNotification::Message { + message: RelayMessage::Event { event, .. }, + .. + } => { + self.update_machine(&event) + .await + .expect("Failed to update machine"); + } + + _ => {} + } + } + + let sub_id = self + .client + .subscribe(self.started_at, self.machines.keys().cloned()) + .await + .expect("Failed to subscribe events"); + + loop { + let notification = notifications + .recv() + .await + .expect("Failed to receive notification"); + tracing::debug!("Received notification: {:?}", notification); + + match notification { + RelayPoolNotification::Shutdown => panic!("Relay pool shutdown"), + + RelayPoolNotification::Message { + message: + RelayMessage::Closed { + message, + subscription_id, + }, + .. + } if subscription_id == sub_id => { + tracing::error!("Subscription closed: {}", message); + panic!("Subscription closed: {message}"); + } + + RelayPoolNotification::Message { + message: RelayMessage::EndOfStoredEvents(subscription_id), + .. + } if subscription_id == sub_id => {} + + RelayPoolNotification::Message { + message: + RelayMessage::Event { + event, + subscription_id, + }, + .. + } if subscription_id == sub_id => { + let Ok(message) = + serde_json::from_str::(&event.content) + else { + tracing::error!("Failed to parse message: {:?}", event); + continue; + }; + + self.handle_message(&event, &message) + .await + .expect("Failed to handle message"); + } + + _ => {} + } + } + }; + + futures::join!(relay_checker, message_handler); + } + + async fn handle_message( + &mut self, + event: &Event, + message: &DephyDechargeMessage, + ) -> Result<(), Error> { + match message { + DephyDechargeMessage::Request { + to_status, + initial_request, + reason, + payload, + } => { + if event.pubkey != self.admin_pubkey + && *reason != DephyDechargeStatusReason::UserRequest + { + tracing::error!( + "User can only use reason UserRequest, skip event: {:?}", + event + ); + } + + let Some(mention) = extract_mention(event) else { + tracing::error!("Machine not mentioned in event, skip event: {:?}", event); + return Ok(()); + }; + + let Ok(machine_pubkey) = PublicKey::parse(mention) else { + tracing::error!("Failed to parse machine pubkey, skip event: {:?}", mention); + return Ok(()); + }; + + let Some(machine) = self.machines.get(&machine_pubkey) else { + tracing::error!("Machine not controlled by us, skip event: {:?}", mention); + return Ok(()); + }; + + if machine.status == *to_status { + tracing::error!( + "Machine already in requested status, skip event: {:?}", + event + ); + return Ok(()); + } + + if *to_status == DephyDechargeStatus::Available { + if *reason == DephyDechargeStatusReason::UserRequest { + tracing::error!( + "User cannot manually stop machine, skip event: {:?}", + event + ); + return Ok(()); + } + + if let Some(ref original_request) = machine.initial_request { + if original_request != initial_request { + tracing::error!( + "Machine already in working status with different request, skip event: {:?}", + event + ); + return Ok(()); + } + } + } + + let Ok(parsed_payload) = + serde_json::from_str::(payload) + else { + tracing::error!("Failed to parse payload, skip event: {:?}", payload); + return Ok(()); + }; + + match dephy_balance_payment_sdk::check_eligible( + &self.solana_rpc_url, + &parsed_payload.user, + parsed_payload.nonce, + PREPAID_AMOUNT, + &parsed_payload.recover_info, + ) + .await + { + Err(e) => { + tracing::error!( + "Failed to check eligible, error: {:?} skip event: {:?}", + e, + event + ); + return Ok(()); + } + + Ok(false) => { + tracing::error!("User not eligible, skip event: {:?}", event); + return Ok(()); + } + Ok(true) => {} + } + + self.client + .send_event(mention, &DephyDechargeMessage::Status { + status: *to_status, + reason: *reason, + initial_request: event.id, + payload: serde_json::to_string(&DephyDechargeMessageStatusPayload { + user: parsed_payload.user.clone(), + nonce: parsed_payload.nonce, + recover_info: parsed_payload.recover_info.clone(), + })?, + }) + .await?; + + // TODO: Should check this by machine api + if *to_status == DephyDechargeStatus::Working { + let client = self.client.clone(); + let mention = mention.to_string(); + let event_id = event.id; + tokio::spawn(async move { + tokio::time::sleep(std::time::Duration::from_secs(60)).await; + client + .send_event(&mention, &DephyDechargeMessage::Status { + status: DephyDechargeStatus::Available, + reason: DephyDechargeStatusReason::UserBehaviour, + initial_request: event_id, + payload: serde_json::to_string( + &DephyDechargeMessageStatusPayload { + user: parsed_payload.user.clone(), + nonce: parsed_payload.nonce, + recover_info: parsed_payload.recover_info, + }, + ) + .unwrap(), + }) + .await + .unwrap(); + }); + } + } + DephyDechargeMessage::Status { .. } => self.update_machine(event).await?, + } + Ok(()) + } +} diff --git a/dephy-vending_machine-examples/examples/decharge-controller/src/node/mod.rs b/dephy-vending_machine-examples/examples/decharge-controller/src/node/mod.rs new file mode 100644 index 0000000..e4ecd47 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/src/node/mod.rs @@ -0,0 +1,3 @@ +mod message_handler; + +pub use message_handler::MessageHandler; diff --git a/dephy-vending_machine-examples/examples/decharge-controller/src/relay_client.rs b/dephy-vending_machine-examples/examples/decharge-controller/src/relay_client.rs new file mode 100644 index 0000000..de4b2b8 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/src/relay_client.rs @@ -0,0 +1,182 @@ +use nostr::Event; +use nostr::EventBuilder; +use nostr::Filter; +use nostr::Keys; +use nostr::PublicKey; +use nostr::SingleLetterTag; +use nostr::SubscriptionId; +use nostr::Tag; +use nostr::Timestamp; +use nostr_sdk::prelude::ReqExitPolicy; +use nostr_sdk::Client; +use nostr_sdk::RelayPoolNotification; +use nostr_sdk::RelayStatus; +use nostr_sdk::SubscribeAutoCloseOptions; +use tokio::sync::broadcast::Receiver; + +const EVENT_KIND: nostr::Kind = nostr::Kind::Custom(1573); +const MENTION_TAG: SingleLetterTag = SingleLetterTag::lowercase(nostr::Alphabet::P); +const SESSION_TAG: SingleLetterTag = SingleLetterTag::lowercase(nostr::Alphabet::S); + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("Nostr client error: {0}")] + NostrClient(#[from] nostr_sdk::client::Error), + #[error("Serde json error: {0}")] + SerdeJson(#[from] serde_json::Error), + #[error("Send event error: {0}")] + SendEvent(String), +} + +#[derive(Clone)] +pub struct RelayClient { + client: Client, + session: String, +} + +impl RelayClient { + pub async fn new( + nostr_relay: &str, + keys: &Keys, + session: &str, + max_notification_size: usize, + ) -> Result { + let client_opts = + nostr_sdk::Options::default().notification_channel_size(max_notification_size); + + let client = Client::builder() + .signer(keys.clone()) + .opts(client_opts) + .build(); + + client.add_relay(nostr_relay).await?; + client.connect().await; + + Ok(Self { + client, + session: session.to_string(), + }) + } + + pub async fn run_relay_checker(self, interval: std::time::Duration) { + loop { + tokio::time::sleep(interval).await; + + let connected_relay_count = self + .client + .relays() + .await + .values() + .filter(|relay| relay.status() == RelayStatus::Connected) + .count(); + + if connected_relay_count == 0 { + panic!("Lost connection to relay"); + } + } + } + + pub fn notifications(&self) -> Receiver { + self.client.notifications() + } + + pub async fn subscribe_last_event( + &self, + until: Timestamp, + author: Option<&PublicKey>, + mention: &PublicKey, + ) -> Result { + let mut filter = Filter::new(); + + filter = filter + .kind(EVENT_KIND) + .until(until) + .custom_tag(SESSION_TAG, [&self.session]) + .custom_tag(MENTION_TAG, [mention.to_hex()]) + .limit(1); + + if let Some(author) = author { + filter = filter.author(*author) + } + + let close_option = + SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); + let output = self + .client + .subscribe(vec![filter], Some(close_option)) + .await?; + + Ok(output.id().clone()) + } + + pub async fn subscribe( + &self, + since: Timestamp, + mentions: I, + ) -> Result + where + I: IntoIterator, + { + let filter = Filter::new() + .kind(EVENT_KIND) + .since(since) + .custom_tag(SESSION_TAG, [&self.session]) + .custom_tag(MENTION_TAG, mentions.into_iter().map(|pk| pk.to_hex())); + + let output = self.client.subscribe(vec![filter], None).await?; + + Ok(output.id().clone()) + } + + pub async fn subscribe_all(&self, since: Option) -> Result { + let mut filter = Filter::new() + .kind(EVENT_KIND) + .custom_tag(SESSION_TAG, [&self.session]); + + if let Some(since) = since { + filter = filter.since(since); + } + + let output = self.client.subscribe(vec![filter], None).await?; + + Ok(output.id().clone()) + } + + pub async fn send_event(&self, to: &str, message: &M) -> Result<(), Error> + where M: serde::Serialize + std::fmt::Debug { + let content = serde_json::to_string(message)?; + + let event_builder = EventBuilder::new(EVENT_KIND, content).tags([ + Tag::parse(["s".to_string(), self.session.clone()]).unwrap(), + Tag::parse(["p".to_string(), to.to_string()]).unwrap(), + ]); + + let res = self.client.send_event_builder(event_builder).await?; + + if !res.failed.is_empty() { + for (relay_url, err) in res.failed.iter() { + tracing::error!("failed to send event to {} err: {:?}", relay_url, err); + } + return Err(Error::SendEvent(format!( + "Failed to send event {message:?} to relay" + ))); + } + + Ok(()) + } +} + +pub fn extract_mention(event: &Event) -> Option<&str> { + event + .tags + .iter() + .filter_map(|tag| { + if tag.single_letter_tag() == Some(MENTION_TAG) { + tag.content() + } else { + None + } + }) + .next() +} diff --git a/dephy-vending_machine-examples/examples/decharge-controller/src/server/message_handler.rs b/dephy-vending_machine-examples/examples/decharge-controller/src/server/message_handler.rs new file mode 100644 index 0000000..0d87660 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/src/server/message_handler.rs @@ -0,0 +1,254 @@ +use nostr::Event; +use nostr::PublicKey; +use nostr::RelayMessage; +use nostr::Timestamp; +use nostr_sdk::RelayPoolNotification; +use tokio::sync::oneshot; + +use crate::message::DephyDechargeMessage; +use crate::message::DephyDechargeMessageStatusPayload; +use crate::message::DephyDechargeStatus; +use crate::message::DephyDechargeStatusReason; +use crate::relay_client::extract_mention; +use crate::server::State; +use crate::RelayClient; + +/// MAX_DEVIATION_SECONDS * 4 +/// MAX_DEVIATION_SECONDS is from dephy_messaging_network crate. +const TIME_BACKTRACE_OF_INITIAL_RETRIEVE: std::time::Duration = + std::time::Duration::from_secs(30 * 4); + +const PREPAID_AMOUNT: u64 = 10_000_000; +const TRANSFER_AMOUNT: u64 = 5_000_000; + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("IO error: {0}")] + Io(#[from] std::io::Error), + #[error("Server state error: {0}")] + State(#[from] crate::server::state::Error), + #[error("Serde json error: {0}")] + SerdeJson(#[from] serde_json::Error), + #[error("Nostr key error: {0}")] + NostrKey(#[from] nostr::key::Error), + #[error("Relay client error: {0}")] + RelayClient(#[from] crate::relay_client::Error), +} + +pub struct MessageHandler { + client: RelayClient, + state: State, + solana_rpc_url: String, + solana_keypair_path: String, + initial_notifier: Option>, +} + +impl MessageHandler { + pub fn new( + client: RelayClient, + state: State, + solana_rpc_url: &str, + solana_keypair_path: &str, + initial_notifier: Option>, + ) -> Self { + Self { + client, + state, + solana_rpc_url: solana_rpc_url.to_string(), + solana_keypair_path: solana_keypair_path.to_string(), + initial_notifier, + } + } + + pub async fn run(mut self) { + let last_processed_event = self + .state + .db_get_last_processed_event() + .await + .expect("Failed to get last processed event"); + + let since = last_processed_event.as_ref().map(|event| { + Timestamp::from_secs(event.created_at as u64) - TIME_BACKTRACE_OF_INITIAL_RETRIEVE + }); + let last_event_id = last_processed_event.map(|event| event.event_id); + + let mut notifications = self.client.notifications(); + self.client + .subscribe_all(since) + .await + .expect("Failed to subscribe events"); + + let checking_client = self.client.clone(); + let relay_checker = async move { + checking_client + .run_relay_checker(std::time::Duration::from_secs(10)) + .await + }; + + let message_handler = async move { + let mut reached_last_event = last_event_id.is_none(); + + loop { + let notification = notifications + .recv() + .await + .expect("Failed to receive notification"); + tracing::debug!("Received notification: {:?}", notification); + + match notification { + RelayPoolNotification::Shutdown => panic!("Relay pool shutdown"), + RelayPoolNotification::Message { + message: RelayMessage::Closed { message, .. }, + .. + } => { + tracing::error!("Subscription closed: {}", message); + panic!("Subscription closed: {message}"); + } + RelayPoolNotification::Message { + message: RelayMessage::EndOfStoredEvents { .. }, + .. + } => { + if !reached_last_event { + tracing::error!( + "Not reached last processed event: {last_event_id:?}, but received end of stored events" + ); + panic!("Not reached last processed event"); + } + + tracing::info!("End of stored events, notifying the checker"); + + let Some(notifier) = self.initial_notifier.take() else { + tracing::info!("No initial_notifier found, will skip notifying"); + continue; + }; + + notifier.send(()).expect("Failed to notify checker start"); + } + RelayPoolNotification::Message { + message: RelayMessage::Event { event, .. }, + .. + } => { + if !reached_last_event { + let last_event_id = last_event_id.as_deref().unwrap(); + + if event.id.to_hex() == last_event_id { + tracing::info!( + "Reached last processed event: {last_event_id}, start handling events" + ); + reached_last_event = true; + } + + continue; + } + + let Ok(message) = + serde_json::from_str::(&event.content) + else { + tracing::error!("Failed to parse message: {:?}", event); + continue; + }; + + self.handle_message(&event, &message) + .await + .expect("Failed to handle message"); + } + _ => {} + } + } + }; + + futures::join!(relay_checker, message_handler); + } + + async fn handle_message( + &self, + event: &Event, + message: &DephyDechargeMessage, + ) -> Result<(), Error> { + tracing::debug!("Handling message: {:?}", message); + let received_id = self + .state + .db_record_received_event(&event.id.to_hex(), event.created_at.as_u64() as i64) + .await?; + + match message { + DephyDechargeMessage::Status { + status: DephyDechargeStatus::Working, + reason: DephyDechargeStatusReason::UserRequest, + initial_request, + payload, + } => { + let Some(mention) = extract_mention(event) else { + tracing::error!("Machine not mentioned in event, skip event: {:?}", event); + return Ok(()); + }; + + if PublicKey::parse(mention).is_err() { + tracing::error!("Failed to parse machine pubkey, skip event: {:?}", mention); + return Ok(()); + }; + + let parsed_payload = + serde_json::from_str::(payload)?; + + if let Err(e) = dephy_balance_payment_sdk::lock( + &self.solana_rpc_url, + &self.solana_keypair_path, + &parsed_payload.user, + PREPAID_AMOUNT, + &parsed_payload.recover_info, + ) + .await + { + tracing::error!("Failed to lock error: {:?} event: {:?}", e, event); + + self.client + .send_event(mention, &DephyDechargeMessage::Request { + to_status: DephyDechargeStatus::Available, + reason: DephyDechargeStatusReason::LockFailed, + initial_request: *initial_request, + payload: payload.to_string(), + }) + .await? + } + } + DephyDechargeMessage::Status { + status: DephyDechargeStatus::Available, + reason: DephyDechargeStatusReason::UserBehaviour, + payload, + .. + } => { + let Some(mention) = extract_mention(event) else { + tracing::error!("Machine not mentioned in event, skip event: {:?}", event); + return Ok(()); + }; + + if PublicKey::parse(mention).is_err() { + tracing::error!("Failed to parse machine pubkey, skip event: {:?}", mention); + return Ok(()); + }; + + let parsed_payload = + serde_json::from_str::(payload)?; + + if let Err(e) = dephy_balance_payment_sdk::settle( + &self.solana_rpc_url, + &self.solana_keypair_path, + &parsed_payload.user, + parsed_payload.nonce, + TRANSFER_AMOUNT, + ) + .await + { + tracing::error!("Failed to settle error: {:?} event: {:?}", e, event); + } + } + _ => {} + } + + self.state.db_record_event_processed(received_id).await?; + + Ok(()) + } +} diff --git a/dephy-vending_machine-examples/examples/decharge-controller/src/server/mod.rs b/dephy-vending_machine-examples/examples/decharge-controller/src/server/mod.rs new file mode 100644 index 0000000..ad1f7a3 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/src/server/mod.rs @@ -0,0 +1,5 @@ +mod message_handler; +mod state; + +pub use message_handler::MessageHandler; +pub use state::State; diff --git a/dephy-vending_machine-examples/examples/decharge-controller/src/server/state.rs b/dephy-vending_machine-examples/examples/decharge-controller/src/server/state.rs new file mode 100644 index 0000000..ff4bb11 --- /dev/null +++ b/dephy-vending_machine-examples/examples/decharge-controller/src/server/state.rs @@ -0,0 +1,123 @@ +use sea_query::Expr; +use sea_query::Iden; +use sea_query::Order; +use sea_query::PostgresQueryBuilder; +use sea_query::Query; +use sea_query::SimpleExpr; +use sea_query::Value; +use sea_query_binder::SqlxBinder; +use sea_query_binder::SqlxValues; + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("SQL build error: {0}")] + SqlBuild(#[from] sea_query::error::Error), + #[error("SQL execute error: {0}")] + SqlExecute(#[from] sqlx::Error), +} + +#[derive(Iden, Clone, Copy)] +enum ReceivedEvents { + Id, + Table, + EventId, + CreatedAt, + IsProcessed, +} + +const RECEIVED_EVENT_RECORD_COLUMNS: [ReceivedEvents; 3] = [ + ReceivedEvents::EventId, + ReceivedEvents::CreatedAt, + ReceivedEvents::IsProcessed, +]; +#[derive(sqlx::FromRow, Debug)] +pub struct ReceivedEventRecord { + pub event_id: String, + pub created_at: i64, + pub is_processed: bool, +} + +pub struct State { + db: sqlx::PgPool, +} + +impl State { + pub fn new(db: sqlx::PgPool) -> Self { + Self { db } + } + + pub async fn db_get_last_processed_event(&self) -> Result, Error> { + let (sql, values) = Query::select() + .columns(RECEIVED_EVENT_RECORD_COLUMNS) + .from(ReceivedEvents::Table) + .and_where(Expr::col(ReceivedEvents::IsProcessed).eq(true)) + // Note: Should not use created_at for sorting. + // It is not unique and the messages may not be received in the order of creation. + .order_by(ReceivedEvents::Id, Order::Desc) + .limit(1) + .build_sqlx(PostgresQueryBuilder); + + tracing::debug!("will execute: {sql} with {values:?}"); + + let row = sqlx::query_as_with::<_, ReceivedEventRecord, _>(&sql, values) + .fetch_optional(&self.db) + .await?; + + Ok(row) + } + + pub async fn db_record_received_event( + &self, + event_id: &str, + created_at: i64, + ) -> Result { + let (sql, values) = Query::insert() + .into_table(ReceivedEvents::Table) + .columns([ + ReceivedEvents::EventId, + ReceivedEvents::CreatedAt, + ReceivedEvents::IsProcessed, + ]) + .values( + [ + Value::from(event_id), + Value::from(created_at), + Value::from(false), + ] + .map(SimpleExpr::Value), + )? + .returning(Query::returning().columns([ReceivedEvents::Id])) + .build_sqlx(PostgresQueryBuilder); + + let row = sqlx::query_as_with::<_, (i64,), _>(&sql, values) + .fetch_one(&self.db) + .await?; + + Ok(row.0) + } + + // This method is isolated because updating the event to processed may be part of a transaction. + fn sql_received_event_is_processed(received_id: i64) -> (String, SqlxValues) { + let (sql, values) = Query::update() + .table(ReceivedEvents::Table) + .values([( + ReceivedEvents::IsProcessed, + SimpleExpr::Value(Value::from(true)), + )]) + .and_where(Expr::col(ReceivedEvents::Id).eq(received_id)) + .build_sqlx(PostgresQueryBuilder); + (sql, values) + } + + pub async fn db_record_event_processed(&self, received_id: i64) -> Result<(), Error> { + let (received_sql, received_values) = State::sql_received_event_is_processed(received_id); + tracing::debug!("will execute: {received_sql} with {received_values:?}"); + + sqlx::query_with(&received_sql, received_values) + .execute(&self.db) + .await?; + + Ok(()) + } +} diff --git a/dephy-vending_machine-examples/examples/gacha-controller/Cargo.toml b/dephy-vending_machine-examples/examples/gacha-controller/Cargo.toml new file mode 100644 index 0000000..4252cea --- /dev/null +++ b/dephy-vending_machine-examples/examples/gacha-controller/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "dephy-gacha-controller" +version = "0.1.0" +edition = "2021" +license.workspace = true + +[dependencies] +clap = { workspace = true } +dephy-balance-payment-sdk = { workspace = true } +futures = { workspace = true } +nostr = { workspace = true } +nostr-sdk = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true, features = ["process", "rt-multi-thread"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["env-filter"] } diff --git a/dephy-vending_machine-examples/examples/gacha-controller/README.md b/dephy-vending_machine-examples/examples/gacha-controller/README.md new file mode 100644 index 0000000..df35ed2 --- /dev/null +++ b/dephy-vending_machine-examples/examples/gacha-controller/README.md @@ -0,0 +1,52 @@ +# dephy-gacha-controller + +## Prepare + +In this example, you should have a messaging network running on `ws://127.0.0.1:8000`. +You can modify `--nostr-relay` if it is running on a different address. + +To run a messaging network you need a postgresql database with schema: + +```sql +CREATE TABLE IF NOT EXISTS events ( + id bigserial PRIMARY KEY, + event_id character varying NOT NULL, + prev_event_id character varying NOT NULL, + pubkey character varying NOT NULL, + created_at bigint NOT NULL, + original character varying NOT NULL, + "session" character varying NOT NULL, + mention character varying, + + CONSTRAINT events_unique_event_id + UNIQUE (event_id), + + CONSTRAINT events_unique_pubkey_session_prev_event_id + UNIQUE (pubkey, session, prev_event_id) +); +``` + +To run a messaging network by docker: + +```shell +docker run --name dephy-messaging-network --restart=always --network="host" -d dephyio/dephy-messaging-network:master serve --pg-url 'postgresql://:@
/' +``` + +## Run Controller (this is on gacha equipment side) + +The controller daemon need your solana keypair. + +```shell +mkdir data +# copy your keypair to data/solana-keypair +``` + +```shell +cargo run --bin dephy-gacha-controller -- --nostr-relay ws://127.0.0.1:8000 --machine-pubkeys 91550af28891a6ac6c73e0d415ed5ee9ea5603ef6d276df623a8b80254519ab2 --admin-pubkey --solana-rpc-url https://api.devnet.solana.com +``` + +## Cli Example (it simulates the process of inserting a coin) + +```shell +cargo run --example cli -- --nostr-relay ws://127.0.0.1:8000 --machine-pubkey 91550af28891a6ac6c73e0d415ed5ee9ea5603ef6d276df623a8b80254519ab2 --user --nonce --recover-info +``` diff --git a/dephy-vending_machine-examples/examples/gacha-controller/examples/cli.rs b/dephy-vending_machine-examples/examples/gacha-controller/examples/cli.rs new file mode 100644 index 0000000..77576c6 --- /dev/null +++ b/dephy-vending_machine-examples/examples/gacha-controller/examples/cli.rs @@ -0,0 +1,158 @@ +use std::path::PathBuf; + +use clap::value_parser; +use clap::Arg; +use clap::ArgAction; +use clap::ArgMatches; +use clap::Command; +use dephy_gacha_controller::message::DephyGachaMessage; +use dephy_gacha_controller::message::DephyGachaMessageRequestPayload; +use dephy_gacha_controller::message::DephyGachaStatus; +use dephy_gacha_controller::message::DephyGachaStatusReason; +use nostr::Keys; +use nostr::Timestamp; +use nostr_sdk::EventId; + +const SESSION: &str = "dephy-gacha-controller"; + +fn parse_args() -> Command { + Command::new("dephy-gacha-controller-cli") + .arg_required_else_help(true) + .about("Dephy gacha controller") + .version(dephy_gacha_controller::VERSION) + .arg( + Arg::new("NOSTR_RELAY") + .long("nostr-relay") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Nostr relay address"), + ) + .arg( + Arg::new("KEY_FILE") + .long("key-file") + .num_args(1) + .default_value("data/key") + .value_parser(value_parser!(PathBuf)) + .action(ArgAction::Set) + .help("Path to the file containing the hex or bech32 secret key"), + ) + .arg( + Arg::new("MACHINE_PUBKEY") + .long("machine-pubkey") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Machine public keys, comma separated"), + ) + .arg( + Arg::new("user") + .long("user") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("User public key"), + ) + .arg( + Arg::new("nonce") + .long("nonce") + .num_args(1) + .required(true) + .value_parser(value_parser!(u64)) + .action(ArgAction::Set) + .help("Nonce"), + ) + .arg( + Arg::new("recover_info") + .long("recover-info") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Recover info"), + ) +} + +async fn cli(args: &ArgMatches) { + let nostr_relay = args.get_one::("NOSTR_RELAY").unwrap(); + let key_file_path = args.get_one::("KEY_FILE").unwrap(); + let keys = read_or_generate_keypair(key_file_path); + let machine_pubkey = args + .get_one::("MACHINE_PUBKEY") + .unwrap() + .parse() + .expect("Invalid machine pubkey"); + let user = args.get_one::("user").unwrap(); + let nonce = args.get_one::("nonce").unwrap(); + let recover_info = args.get_one::("recover_info").unwrap(); + + let client = dephy_gacha_controller::RelayClient::new(nostr_relay, &keys, SESSION, 4096) + .await + .expect("Failed to connect to relay"); + + let mut notifications = client.notifications(); + client + .subscribe(Timestamp::now(), [machine_pubkey]) + .await + .expect("Failed to subscribe"); + + let handler = tokio::spawn(async move { + loop { + let notification = notifications.recv().await; + tracing::info!("Received notification: {:?}", notification); + } + }); + + let payload = serde_json::to_string(&DephyGachaMessageRequestPayload { + user: user.clone(), + nonce: *nonce, + recover_info: recover_info.clone(), + }) + .expect("Failed to serialize payload"); + + client + .send_event(&machine_pubkey.to_hex(), &DephyGachaMessage::Request { + to_status: DephyGachaStatus::Working, + reason: DephyGachaStatusReason::UserRequest, + initial_request: EventId::all_zeros(), + payload, + }) + .await + .expect("Failed to send event"); + + handler.await.expect("Notification handler failed"); +} + +fn read_or_generate_keypair(path: &PathBuf) -> Keys { + let keys = std::fs::read_to_string(path) + .map(|content| content.trim().parse().expect("Invalid key")) + .unwrap_or_else(|_| { + tracing::info!( + "Key file not found, generating a new one at: {}", + path.display() + ); + let keys = Keys::generate(); + std::fs::write(path, keys.secret_key().to_secret_hex()) + .unwrap_or_else(|e| panic!("Failed to write key {}: {e:?}", path.display())); + keys + }); + + let pubkey_path = path.with_extension("pub"); + std::fs::write(&pubkey_path, keys.public_key().to_hex()).unwrap_or_else(|e| { + panic!( + "Failed to write public key {}: {e:?}", + pubkey_path.display() + ) + }); + + keys +} + +#[tokio::main] +async fn main() { + let _ = tracing_subscriber::fmt() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .try_init(); + + let cmd = parse_args(); + cli(&cmd.get_matches()).await; +} diff --git a/dephy-vending_machine-examples/examples/gacha-controller/src/lib.rs b/dephy-vending_machine-examples/examples/gacha-controller/src/lib.rs new file mode 100644 index 0000000..210058e --- /dev/null +++ b/dephy-vending_machine-examples/examples/gacha-controller/src/lib.rs @@ -0,0 +1,8 @@ +pub mod message; +pub mod node; +mod relay_client; + +/// dephy-gacha-controller version +pub const VERSION: &str = env!("CARGO_PKG_VERSION"); + +pub use relay_client::RelayClient; diff --git a/dephy-vending_machine-examples/examples/gacha-controller/src/main.rs b/dephy-vending_machine-examples/examples/gacha-controller/src/main.rs new file mode 100644 index 0000000..47078d1 --- /dev/null +++ b/dephy-vending_machine-examples/examples/gacha-controller/src/main.rs @@ -0,0 +1,147 @@ +use std::path::PathBuf; + +use clap::value_parser; +use clap::Arg; +use clap::ArgAction; +use clap::ArgMatches; +use clap::Command; +use nostr::Keys; + +const SESSION: &str = "dephy-gacha-controller"; + +fn parse_args() -> Command { + Command::new("dephy-gacha-controller-node") + .arg_required_else_help(true) + .about("Dephy gacha controller node daemon") + .version(dephy_gacha_controller::VERSION) + .arg( + Arg::new("NOSTR_RELAY") + .long("nostr-relay") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Nostr relay address"), + ) + .arg( + Arg::new("KEY_FILE") + .long("key-file") + .num_args(1) + .default_value("data/key") + .value_parser(value_parser!(PathBuf)) + .action(ArgAction::Set) + .help("Path to the file containing the hex or bech32 secret key"), + ) + .arg( + Arg::new("ADMIN_PUBKEY") + .long("admin-pubkey") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Admin public key"), + ) + .arg( + Arg::new("MACHINE_PUBKEYS") + .long("machine-pubkeys") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Machine public keys, comma separated"), + ) + .arg( + Arg::new("SOLANA_RPC_URL") + .long("solana-rpc-url") + .num_args(1) + .required(true) + .action(ArgAction::Set) + .help("Solana RPC URL"), + ) + .arg( + Arg::new("SOLANA_KEYPAIR") + .long("solana-keypair") + .num_args(1) + .default_value("data/solana-keypair") + .value_parser(value_parser!(PathBuf)) + .action(ArgAction::Set) + .help("Solana keypair path"), + ) +} + +async fn controller(args: &ArgMatches) { + let nostr_relay = args.get_one::("NOSTR_RELAY").unwrap(); + let key_file_path = args.get_one::("KEY_FILE").unwrap(); + let keys = read_or_generate_keypair(key_file_path); + let admin_pubkey = args + .get_one::("ADMIN_PUBKEY") + .unwrap() + .parse() + .expect("Invalid admin pubkey"); + let machine_pubkeys = args + .get_one::("MACHINE_PUBKEYS") + .unwrap() + .split(',') + .map(|s| s.parse().expect("Invalid machine pubkey")) + .collect(); + let solana_rpc_url = args.get_one::("SOLANA_RPC_URL").unwrap(); + let solana_keypair_path = args.get_one::("SOLANA_KEYPAIR").unwrap(); + if !solana_keypair_path.exists() { + panic!( + "Solana keypair file not found: {}", + solana_keypair_path.display() + ); + } + + println!("nostr relay: {}", nostr_relay); + println!("pubkey: {}", keys.public_key()); + + let client = dephy_gacha_controller::RelayClient::new(nostr_relay, &keys, SESSION, 4096) + .await + .expect("Failed to connect to relay"); + + let message_handler = dephy_gacha_controller::node::MessageHandler::new( + client, + solana_rpc_url, + solana_keypair_path + .to_str() + .expect("Invalid solana keypair path"), + keys.public_key(), + admin_pubkey, + machine_pubkeys, + ); + + message_handler.run().await +} + +fn read_or_generate_keypair(path: &PathBuf) -> Keys { + let keys = std::fs::read_to_string(path) + .map(|content| content.trim().parse().expect("Invalid key")) + .unwrap_or_else(|_| { + tracing::info!( + "Key file not found, generating a new one at: {}", + path.display() + ); + let keys = Keys::generate(); + std::fs::write(path, keys.secret_key().to_secret_hex()) + .unwrap_or_else(|e| panic!("Failed to write key {}: {e:?}", path.display())); + keys + }); + + let pubkey_path = path.with_extension("pub"); + std::fs::write(&pubkey_path, keys.public_key().to_hex()).unwrap_or_else(|e| { + panic!( + "Failed to write public key {}: {e:?}", + pubkey_path.display() + ) + }); + + keys +} + +#[tokio::main] +async fn main() { + let _ = tracing_subscriber::fmt() + .with_env_filter(tracing_subscriber::EnvFilter::from_default_env()) + .try_init(); + + let cmd = parse_args(); + controller(&cmd.get_matches()).await; +} diff --git a/dephy-vending_machine-examples/examples/gacha-controller/src/message.rs b/dephy-vending_machine-examples/examples/gacha-controller/src/message.rs new file mode 100644 index 0000000..b8a7cd3 --- /dev/null +++ b/dephy-vending_machine-examples/examples/gacha-controller/src/message.rs @@ -0,0 +1,50 @@ +use nostr::EventId; +use serde::Deserialize; +use serde::Serialize; + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[repr(u8)] +pub enum DephyGachaStatus { + Available = 1, + Working = 2, +} + +#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)] +#[repr(u8)] +pub enum DephyGachaStatusReason { + UserRequest = 1, + AdminRequest = 2, + UserBehaviour = 3, + Reset = 4, + LockFailed = 5, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum DephyGachaMessage { + Request { + to_status: DephyGachaStatus, + reason: DephyGachaStatusReason, + initial_request: EventId, + payload: String, + }, + Status { + status: DephyGachaStatus, + reason: DephyGachaStatusReason, + initial_request: EventId, + payload: String, + }, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DephyGachaMessageRequestPayload { + pub user: String, + pub nonce: u64, + pub recover_info: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DephyGachaMessageStatusPayload { + pub user: String, + pub nonce: u64, + pub recover_info: String, +} diff --git a/dephy-vending_machine-examples/examples/gacha-controller/src/node/message_handler.rs b/dephy-vending_machine-examples/examples/gacha-controller/src/node/message_handler.rs new file mode 100644 index 0000000..465ff06 --- /dev/null +++ b/dephy-vending_machine-examples/examples/gacha-controller/src/node/message_handler.rs @@ -0,0 +1,378 @@ +use std::collections::HashMap; +use std::collections::HashSet; + +use nostr::Event; +use nostr::EventId; +use nostr::PublicKey; +use nostr::RelayMessage; +use nostr::Timestamp; +use nostr_sdk::RelayPoolNotification; + +use crate::message::DephyGachaMessage; +use crate::message::DephyGachaMessageRequestPayload; +use crate::message::DephyGachaMessageStatusPayload; +use crate::message::DephyGachaStatus; +use crate::message::DephyGachaStatusReason; +use crate::relay_client::extract_mention; +use crate::RelayClient; + +const PAY_AMOUNT: u64 = 5_000_000; + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("Serde json error: {0}")] + SerdeJson(#[from] serde_json::Error), + #[error("Nostr key error: {0}")] + NostrKey(#[from] nostr::key::Error), + #[error("Relay client error: {0}")] + RelayClient(#[from] crate::relay_client::Error), + #[error("Machine not mentioned in event: {0:?}")] + MachineNotMentioned(Event), + #[error("The machine mentioned by event is not controlled by us: {0:?}")] + MachineNotControlled(Event), + #[error("Only support status event when update machine, but got: {0:?}")] + OnlySupportStatusEventWhenUpdateMachine(Event), +} + +pub struct Machine { + #[allow(dead_code)] + pubkey: PublicKey, + status: DephyGachaStatus, + initial_request: Option, +} + +pub struct MessageHandler { + client: RelayClient, + solana_rpc_url: String, + solana_keypair_path: String, + controller_pubkey: PublicKey, + admin_pubkey: PublicKey, + machines: HashMap, + started_at: Timestamp, +} + +impl MessageHandler { + pub fn new( + client: RelayClient, + solana_rpc_url: &str, + solana_keypair_path: &str, + controller_pubkey: PublicKey, + admin_pubkey: PublicKey, + machine_pubkeys: HashSet, + ) -> Self { + let started_at = Timestamp::now(); + let machines = machine_pubkeys + .into_iter() + .map(|pubkey| { + (pubkey, Machine { + pubkey, + status: DephyGachaStatus::Available, + initial_request: None, + }) + }) + .collect(); + + Self { + client, + solana_rpc_url: solana_rpc_url.to_string(), + solana_keypair_path: solana_keypair_path.to_string(), + controller_pubkey, + admin_pubkey, + machines, + started_at, + } + } + + pub async fn update_machine(&mut self, event: &Event) -> Result<(), Error> { + let mention = PublicKey::parse( + extract_mention(event).ok_or_else(|| Error::MachineNotMentioned(event.clone()))?, + )?; + + let machine = self + .machines + .get_mut(&mention) + .ok_or_else(|| Error::MachineNotControlled(event.clone()))?; + + let message = serde_json::from_str::(&event.content)?; + + match message { + DephyGachaMessage::Request { .. } => { + return Err(Error::OnlySupportStatusEventWhenUpdateMachine( + event.clone(), + )) + } + + DephyGachaMessage::Status { + status, + initial_request, + .. + } => { + machine.status = status; + machine.initial_request = Some(initial_request); + } + } + + Ok(()) + } + + pub async fn run(mut self) { + let mut notifications = self.client.notifications(); + + let checking_client = self.client.clone(); + let relay_checker = async move { + checking_client + .run_relay_checker(std::time::Duration::from_secs(10)) + .await + }; + + let message_handler = async move { + let mut sub_ids = HashMap::new(); + + for machine_pubkey in self.machines.keys().copied() { + let sub_id = self + .client + .subscribe_last_event( + self.started_at, + Some(&self.controller_pubkey), + &machine_pubkey, + ) + .await + .expect("Failed to subscribe events"); + + sub_ids.insert(sub_id, machine_pubkey); + } + + while !sub_ids.is_empty() { + let notification = notifications + .recv() + .await + .expect("Failed to receive notification"); + tracing::debug!("Received notification: {:?}", notification); + + match notification { + RelayPoolNotification::Shutdown => panic!("Relay pool shutdown"), + + RelayPoolNotification::Message { + message: + RelayMessage::Closed { + message, + subscription_id, + }, + .. + } => { + if sub_ids.contains_key(&subscription_id) { + tracing::error!( + "Subscription closed before EndOfStoredEvents: {}", + message + ); + panic!("Subscription closed before EndOfStoredEvents: {message}"); + } + } + + RelayPoolNotification::Message { + message: RelayMessage::EndOfStoredEvents(subscription_id), + .. + } => { + sub_ids.remove(&subscription_id); + } + + RelayPoolNotification::Message { + message: RelayMessage::Event { event, .. }, + .. + } => { + self.update_machine(&event) + .await + .expect("Failed to update machine"); + } + + _ => {} + } + } + + let sub_id = self + .client + .subscribe(self.started_at, self.machines.keys().cloned()) + .await + .expect("Failed to subscribe events"); + + loop { + let notification = notifications + .recv() + .await + .expect("Failed to receive notification"); + tracing::debug!("Received notification: {:?}", notification); + + match notification { + RelayPoolNotification::Shutdown => panic!("Relay pool shutdown"), + + RelayPoolNotification::Message { + message: + RelayMessage::Closed { + message, + subscription_id, + }, + .. + } if subscription_id == sub_id => { + tracing::error!("Subscription closed: {}", message); + panic!("Subscription closed: {message}"); + } + + RelayPoolNotification::Message { + message: RelayMessage::EndOfStoredEvents(subscription_id), + .. + } if subscription_id == sub_id => {} + + RelayPoolNotification::Message { + message: + RelayMessage::Event { + event, + subscription_id, + }, + .. + } if subscription_id == sub_id => { + let Ok(message) = serde_json::from_str::(&event.content) + else { + tracing::error!("Failed to parse message: {:?}", event); + continue; + }; + + self.handle_message(&event, &message) + .await + .expect("Failed to handle message"); + } + + _ => {} + } + } + }; + + futures::join!(relay_checker, message_handler); + } + + async fn handle_message( + &mut self, + event: &Event, + message: &DephyGachaMessage, + ) -> Result<(), Error> { + match message { + DephyGachaMessage::Request { + to_status, + initial_request, + reason, + payload, + } => { + if event.pubkey != self.admin_pubkey + && *reason != DephyGachaStatusReason::UserRequest + { + tracing::error!( + "User can only use reason UserRequest, skip event: {:?}", + event + ); + } + + let Some(mention) = extract_mention(event) else { + tracing::error!("Machine not mentioned in event, skip event: {:?}", event); + return Ok(()); + }; + + let Ok(machine_pubkey) = PublicKey::parse(mention) else { + tracing::error!("Failed to parse machine pubkey, skip event: {:?}", mention); + return Ok(()); + }; + + let Some(machine) = self.machines.get(&machine_pubkey) else { + tracing::error!("Machine not controlled by us, skip event: {:?}", mention); + return Ok(()); + }; + + if machine.status == *to_status { + tracing::error!( + "Machine already in requested status, skip event: {:?}", + event + ); + return Ok(()); + } + + if *to_status == DephyGachaStatus::Available { + if *reason == DephyGachaStatusReason::UserRequest { + tracing::error!( + "User cannot manually stop machine, skip event: {:?}", + event + ); + return Ok(()); + } + + if let Some(ref original_request) = machine.initial_request { + if original_request != initial_request { + tracing::error!( + "Machine already in working status with different request, skip event: {:?}", + event + ); + return Ok(()); + } + } + } + + let Ok(parsed_payload) = + serde_json::from_str::(payload) + else { + tracing::error!("Failed to parse payload, skip event: {:?}", payload); + return Ok(()); + }; + + if let Err(e) = dephy_balance_payment_sdk::pay( + &self.solana_rpc_url, + &self.solana_keypair_path, + &parsed_payload.user, + PAY_AMOUNT, + &parsed_payload.recover_info, + ) + .await + { + tracing::error!("Failed to pay, error: {:?} skip event: {:?}", e, event); + return Ok(()); + }; + + self.client + .send_event(mention, &DephyGachaMessage::Status { + status: *to_status, + reason: *reason, + initial_request: event.id, + payload: serde_json::to_string(&DephyGachaMessageStatusPayload { + user: parsed_payload.user.clone(), + nonce: parsed_payload.nonce, + recover_info: parsed_payload.recover_info.clone(), + })?, + }) + .await?; + + // TODO: Should check this by machine api + if *to_status == DephyGachaStatus::Working { + let client = self.client.clone(); + let mention = mention.to_string(); + let event_id = event.id; + tokio::spawn(async move { + tokio::time::sleep(std::time::Duration::from_secs(10)).await; + client + .send_event(&mention, &DephyGachaMessage::Status { + status: DephyGachaStatus::Available, + reason: DephyGachaStatusReason::UserBehaviour, + initial_request: event_id, + payload: serde_json::to_string(&DephyGachaMessageStatusPayload { + user: parsed_payload.user.clone(), + nonce: parsed_payload.nonce, + recover_info: parsed_payload.recover_info, + }) + .unwrap(), + }) + .await + .unwrap(); + }); + } + } + DephyGachaMessage::Status { .. } => self.update_machine(event).await?, + } + Ok(()) + } +} diff --git a/dephy-vending_machine-examples/examples/gacha-controller/src/node/mod.rs b/dephy-vending_machine-examples/examples/gacha-controller/src/node/mod.rs new file mode 100644 index 0000000..e4ecd47 --- /dev/null +++ b/dephy-vending_machine-examples/examples/gacha-controller/src/node/mod.rs @@ -0,0 +1,3 @@ +mod message_handler; + +pub use message_handler::MessageHandler; diff --git a/dephy-vending_machine-examples/examples/gacha-controller/src/relay_client.rs b/dephy-vending_machine-examples/examples/gacha-controller/src/relay_client.rs new file mode 100644 index 0000000..de4b2b8 --- /dev/null +++ b/dephy-vending_machine-examples/examples/gacha-controller/src/relay_client.rs @@ -0,0 +1,182 @@ +use nostr::Event; +use nostr::EventBuilder; +use nostr::Filter; +use nostr::Keys; +use nostr::PublicKey; +use nostr::SingleLetterTag; +use nostr::SubscriptionId; +use nostr::Tag; +use nostr::Timestamp; +use nostr_sdk::prelude::ReqExitPolicy; +use nostr_sdk::Client; +use nostr_sdk::RelayPoolNotification; +use nostr_sdk::RelayStatus; +use nostr_sdk::SubscribeAutoCloseOptions; +use tokio::sync::broadcast::Receiver; + +const EVENT_KIND: nostr::Kind = nostr::Kind::Custom(1573); +const MENTION_TAG: SingleLetterTag = SingleLetterTag::lowercase(nostr::Alphabet::P); +const SESSION_TAG: SingleLetterTag = SingleLetterTag::lowercase(nostr::Alphabet::S); + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum Error { + #[error("Nostr client error: {0}")] + NostrClient(#[from] nostr_sdk::client::Error), + #[error("Serde json error: {0}")] + SerdeJson(#[from] serde_json::Error), + #[error("Send event error: {0}")] + SendEvent(String), +} + +#[derive(Clone)] +pub struct RelayClient { + client: Client, + session: String, +} + +impl RelayClient { + pub async fn new( + nostr_relay: &str, + keys: &Keys, + session: &str, + max_notification_size: usize, + ) -> Result { + let client_opts = + nostr_sdk::Options::default().notification_channel_size(max_notification_size); + + let client = Client::builder() + .signer(keys.clone()) + .opts(client_opts) + .build(); + + client.add_relay(nostr_relay).await?; + client.connect().await; + + Ok(Self { + client, + session: session.to_string(), + }) + } + + pub async fn run_relay_checker(self, interval: std::time::Duration) { + loop { + tokio::time::sleep(interval).await; + + let connected_relay_count = self + .client + .relays() + .await + .values() + .filter(|relay| relay.status() == RelayStatus::Connected) + .count(); + + if connected_relay_count == 0 { + panic!("Lost connection to relay"); + } + } + } + + pub fn notifications(&self) -> Receiver { + self.client.notifications() + } + + pub async fn subscribe_last_event( + &self, + until: Timestamp, + author: Option<&PublicKey>, + mention: &PublicKey, + ) -> Result { + let mut filter = Filter::new(); + + filter = filter + .kind(EVENT_KIND) + .until(until) + .custom_tag(SESSION_TAG, [&self.session]) + .custom_tag(MENTION_TAG, [mention.to_hex()]) + .limit(1); + + if let Some(author) = author { + filter = filter.author(*author) + } + + let close_option = + SubscribeAutoCloseOptions::default().exit_policy(ReqExitPolicy::ExitOnEOSE); + let output = self + .client + .subscribe(vec![filter], Some(close_option)) + .await?; + + Ok(output.id().clone()) + } + + pub async fn subscribe( + &self, + since: Timestamp, + mentions: I, + ) -> Result + where + I: IntoIterator, + { + let filter = Filter::new() + .kind(EVENT_KIND) + .since(since) + .custom_tag(SESSION_TAG, [&self.session]) + .custom_tag(MENTION_TAG, mentions.into_iter().map(|pk| pk.to_hex())); + + let output = self.client.subscribe(vec![filter], None).await?; + + Ok(output.id().clone()) + } + + pub async fn subscribe_all(&self, since: Option) -> Result { + let mut filter = Filter::new() + .kind(EVENT_KIND) + .custom_tag(SESSION_TAG, [&self.session]); + + if let Some(since) = since { + filter = filter.since(since); + } + + let output = self.client.subscribe(vec![filter], None).await?; + + Ok(output.id().clone()) + } + + pub async fn send_event(&self, to: &str, message: &M) -> Result<(), Error> + where M: serde::Serialize + std::fmt::Debug { + let content = serde_json::to_string(message)?; + + let event_builder = EventBuilder::new(EVENT_KIND, content).tags([ + Tag::parse(["s".to_string(), self.session.clone()]).unwrap(), + Tag::parse(["p".to_string(), to.to_string()]).unwrap(), + ]); + + let res = self.client.send_event_builder(event_builder).await?; + + if !res.failed.is_empty() { + for (relay_url, err) in res.failed.iter() { + tracing::error!("failed to send event to {} err: {:?}", relay_url, err); + } + return Err(Error::SendEvent(format!( + "Failed to send event {message:?} to relay" + ))); + } + + Ok(()) + } +} + +pub fn extract_mention(event: &Event) -> Option<&str> { + event + .tags + .iter() + .filter_map(|tag| { + if tag.single_letter_tag() == Some(MENTION_TAG) { + tag.content() + } else { + None + } + }) + .next() +} diff --git a/dephy-vending_machine-examples/keypairs/bot.demo.json b/dephy-vending_machine-examples/keypairs/bot.demo.json new file mode 100644 index 0000000..33396d4 --- /dev/null +++ b/dephy-vending_machine-examples/keypairs/bot.demo.json @@ -0,0 +1 @@ +[44,207,158,7,241,71,195,163,219,208,30,139,23,10,103,142,141,128,178,105,198,92,182,10,106,135,254,83,66,166,67,43,130,164,191,76,199,232,128,86,121,179,95,252,112,113,109,20,72,95,231,238,212,22,54,11,184,213,97,70,103,19,106,226] diff --git a/dephy-vending_machine-examples/keypairs/user.demo.json b/dephy-vending_machine-examples/keypairs/user.demo.json new file mode 100644 index 0000000..cbafc5b --- /dev/null +++ b/dephy-vending_machine-examples/keypairs/user.demo.json @@ -0,0 +1 @@ +[217,84,19,12,238,222,160,44,140,57,205,228,164,72,186,127,152,217,218,235,201,22,54,234,187,138,129,167,83,9,87,177,196,67,202,217,204,23,61,11,118,126,77,248,143,227,5,39,3,26,126,6,67,228,190,144,149,109,173,251,108,74,221,200] diff --git a/dephy-vending_machine-examples/rustfmt.toml b/dephy-vending_machine-examples/rustfmt.toml new file mode 100644 index 0000000..cb1a6f9 --- /dev/null +++ b/dephy-vending_machine-examples/rustfmt.toml @@ -0,0 +1,13 @@ +edition = "2021" +unstable_features = true +tab_spaces = 4 +hard_tabs = false +reorder_imports = true +format_code_in_doc_comments = true +wrap_comments = false +format_strings = false +imports_granularity = "Item" +group_imports = "StdExternalCrate" +where_single_line = true +trailing_comma = "Vertical" +overflow_delimited_expr = true diff --git a/dephy-vending_machine-examples/taplo.toml b/dephy-vending_machine-examples/taplo.toml new file mode 100644 index 0000000..f028e77 --- /dev/null +++ b/dephy-vending_machine-examples/taplo.toml @@ -0,0 +1,36 @@ +## https://taplo.tamasfe.dev/configuration/#configuration-file + +include = ["**/Cargo.toml"] + +[formatting] +# Align consecutive entries vertically. +align_entries = false +# Append trailing commas for multi-line arrays. +array_trailing_comma = true +# Expand arrays to multiple lines that exceed the maximum column width. +array_auto_expand = true +# Collapse arrays that don't exceed the maximum column width and don't contain comments. +array_auto_collapse = false +# Omit white space padding from single-line arrays +compact_arrays = true +# Omit white space padding from the start and end of inline tables. +compact_inline_tables = false +# Maximum column width in characters, affects array expansion and collapse, this doesn't take whitespace into account. +# Note that this is not set in stone, and works on a best-effort basis. +column_width = 500 +# Indent based on tables and arrays of tables and their subtables, subtables out of order are not indented. +indent_tables = false +# The substring that is used for indentation, should be tabs or spaces (but technically can be anything). +indent_string = ' ' +# Add trailing newline at the end of the file if not present. +trailing_newline = true +# Alphabetically reorder keys that are not separated by empty lines. +reorder_keys = false +# Maximum amount of allowed consecutive blank lines. This does not affect the whitespace at the end of the document, as it is always stripped. +allowed_blank_lines = 1 +# Use CRLF for line endings. +crlf = false + +[[rule]] +keys = ["dependencies", "dev-dependencies", "build-dependencies", "workspace.dependencies"] +formatting = { reorder_keys = true } diff --git a/dephy-vending_machine-examples/typos.toml b/dephy-vending_machine-examples/typos.toml new file mode 100644 index 0000000..2631f4c --- /dev/null +++ b/dephy-vending_machine-examples/typos.toml @@ -0,0 +1,3 @@ +[default.extend-words] +# skip `Ue` +Ue = "Ue"